/*      */ package com.zimbra.cs.mailbox.calendar;
/*      */ 
/*      */ import com.google.common.base.Strings;
/*      */ import com.google.common.collect.Lists;
/*      */ import com.zimbra.common.account.Key.AccountBy;
/*      */ import com.zimbra.common.calendar.Attach;
/*      */ import com.zimbra.common.calendar.Geo;
/*      */ import com.zimbra.common.calendar.ICalTimeZone;
/*      */ import com.zimbra.common.calendar.ParsedDateTime;
/*      */ import com.zimbra.common.calendar.ParsedDuration;
/*      */ import com.zimbra.common.calendar.TimeZoneMap;
/*      */ import com.zimbra.common.calendar.ZCalendar.ICalTok;
/*      */ import com.zimbra.common.calendar.ZCalendar.ZCalendarBuilder;
/*      */ import com.zimbra.common.calendar.ZCalendar.ZComponent;
/*      */ import com.zimbra.common.calendar.ZCalendar.ZParameter;
/*      */ import com.zimbra.common.calendar.ZCalendar.ZProperty;
/*      */ import com.zimbra.common.calendar.ZCalendar.ZVCalendar;
/*      */ import com.zimbra.common.localconfig.DebugConfig;
/*      */ import com.zimbra.common.localconfig.KnownKey;
/*      */ import com.zimbra.common.localconfig.LC;
/*      */ import com.zimbra.common.service.ServiceException;
/*      */ import com.zimbra.common.util.ByteUtil;
/*      */ import com.zimbra.common.util.Log;
/*      */ import com.zimbra.common.util.LogFactory;
/*      */ import com.zimbra.common.util.StringUtil;
/*      */ import com.zimbra.common.util.ZimbraLog;
/*      */ import com.zimbra.cs.account.Account;
/*      */ import com.zimbra.cs.account.Identity;
/*      */ import com.zimbra.cs.account.Provisioning;
/*      */ import com.zimbra.cs.index.Fragment;
/*      */ import com.zimbra.cs.mailbox.CalendarItem;
/*      */ import com.zimbra.cs.mailbox.CalendarItem.Instance;
/*      */ import com.zimbra.cs.mailbox.MailItem.Type;
/*      */ import com.zimbra.cs.mailbox.Mailbox;
/*      */ import com.zimbra.cs.mailbox.MailboxManager;
/*      */ import com.zimbra.cs.mailbox.Metadata;
/*      */ import com.zimbra.cs.mime.MPartInfo;
/*      */ import com.zimbra.cs.mime.Mime;
/*      */ import com.zimbra.cs.util.AccountUtil.AccountAddressMatcher;
/*      */ import java.io.ByteArrayInputStream;
/*      */ import java.io.IOException;
/*      */ import java.io.InputStream;
/*      */ import java.util.ArrayList;
/*      */ import java.util.Arrays;
/*      */ import java.util.HashSet;
/*      */ import java.util.Iterator;
/*      */ import java.util.List;
/*      */ import java.util.Set;
/*      */ import javax.mail.BodyPart;
/*      */ import javax.mail.MessagingException;
/*      */ import javax.mail.Part;
/*      */ import javax.mail.internet.ContentType;
/*      */ import javax.mail.internet.MimeMessage;
/*      */ import javax.mail.internet.MimeMultipart;
/*      */ import javax.mail.internet.MimePart;
/*      */ import org.apache.commons.io.IOUtils;
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ public class Invite
/*      */ {
/*   94 */   private static final boolean OUTLOOK_COMPAT_ALLDAY = LC.calendar_outlook_compatible_allday_events.booleanValue();
/*      */   
/*      */ 
/*      */   public static final String HEADER_SEPARATOR = "*~*~*~*~*~*~*~*~*~*";
/*      */   
/*   99 */   static Log sLog = LogFactory.getLog(Invite.class);
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   private Recurrence.IRecurrence mRecurrence;
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   Invite(MailItem.Type type, String methodStr, TimeZoneMap tzmap, CalendarItem calItem, String uid, String status, String priority, String pctComplete, long completed, String freebusy, String transp, String classProp, ParsedDateTime start, ParsedDateTime end, ParsedDuration duration, Recurrence.IRecurrence recurrence, boolean isOrganizer, ZOrganizer org, List<ZAttendee> attendees, String name, String loc, int flags, String partStat, boolean rsvp, RecurId recurrenceId, long dtstamp, long lastModified, int seqno, int lastFullSeqno, int mailboxId, int mailItemId, int componentNum, boolean sentByMe, String description, String descHtml, String fragment, List<String> comments, List<String> categories, List<String> contacts, Geo geo, String url)
/*      */   {
/*  115 */     setItemType(type);
/*  116 */     this.mMethod = lookupMethod(methodStr);
/*  117 */     this.mTzMap = tzmap;
/*  118 */     this.mCalItem = calItem;
/*  119 */     this.mUid = uid;
/*  120 */     this.mStatus = status;
/*  121 */     this.mPriority = priority;
/*  122 */     this.mPercentComplete = pctComplete;
/*  123 */     this.mCompleted = completed;
/*  124 */     this.mFreeBusy = freebusy;
/*  125 */     this.mTransparency = transp;
/*  126 */     this.mClass = classProp;
/*  127 */     this.mClassSetByMe = sentByMe;
/*  128 */     this.mStart = start;
/*  129 */     this.mEnd = end;
/*  130 */     this.mDuration = duration;
/*  131 */     this.mIsOrganizer = isOrganizer;
/*  132 */     this.mOrganizer = org;
/*  133 */     this.mAttendees = attendees;
/*  134 */     this.mName = (name != null ? name : "");
/*  135 */     this.mLocation = (loc != null ? loc : "");
/*  136 */     this.mFlags = flags;
/*  137 */     this.mPartStat = partStat;
/*  138 */     this.mRsvp = rsvp;
/*  139 */     this.mSeqNo = seqno;
/*      */     
/*      */ 
/*  142 */     this.mLastFullSeqNo = lastFullSeqno;
/*  143 */     setDtStamp(dtstamp);
/*  144 */     setLastModified(lastModified);
/*      */     
/*  146 */     this.mMailboxId = mailboxId;
/*  147 */     this.mMailItemId = mailItemId;
/*  148 */     this.mComponentNum = componentNum;
/*  149 */     this.mSentByMe = sentByMe;
/*  150 */     setDescription(description, descHtml);
/*  151 */     this.mFragment = (fragment != null ? fragment : "");
/*  152 */     this.mComments = (comments != null ? comments : new ArrayList());
/*  153 */     this.mCategories = (categories != null ? categories : new ArrayList());
/*  154 */     this.mContacts = (contacts != null ? contacts : new ArrayList());
/*  155 */     this.mGeo = geo;
/*  156 */     setUrl(url);
/*      */     
/*  158 */     setRecurrence(recurrence);
/*  159 */     setRecurId(recurrenceId);
/*      */   }
/*      */   
/*      */ 
/*  163 */   public Recurrence.IRecurrence getRecurrence() { return this.mRecurrence; }
/*      */   
/*      */   public void setRecurrence(Recurrence.IRecurrence recur) {
/*  166 */     if (this.mRecurrenceId == null) {
/*  167 */       this.mRecurrence = recur;
/*  168 */       setIsRecurrence(this.mRecurrence != null);
/*      */     }
/*      */   }
/*      */   
/*  172 */   private void clearRecurrence() { this.mRecurrence = null;
/*  173 */     setIsRecurrence(false); }
/*      */   
/*  175 */   protected RecurId mRecurrenceId = null;
/*  176 */   public RecurId getRecurId() { return this.mRecurrenceId; }
/*      */   
/*  178 */   public void setRecurId(RecurId rid) { this.mRecurrenceId = rid;
/*      */     
/*  180 */     if (this.mRecurrenceId != null)
/*  181 */       clearRecurrence(); }
/*      */   
/*  183 */   public boolean hasRecurId() { return this.mRecurrenceId != null; }
/*      */   
/*      */ 
/*      */ 
/*  187 */   public String getFragment() { return this.mFragment; }
/*  188 */   public void setFragment(String fragment) { this.mFragment = fragment; }
/*      */   
/*      */ 
/*      */   private boolean mSentByMe;
/*      */   
/*      */   private String mFragment;
/*      */   
/*      */   private static final String FN_ITEMTYPE = "it";
/*      */   
/*      */   private static final String FN_APPT_FLAGS = "af";
/*      */   
/*      */   private static final String FN_ATTENDEE = "at";
/*      */   
/*      */   private static final String FN_SENTBYME = "byme";
/*      */   
/*      */   private static final String FN_CATEGORY = "cat";
/*      */   
/*      */   private static final String FN_CLASS = "cl";
/*      */   private static final String FN_CLASS_SETBYME = "clSetByMe";
/*      */   private static final String FN_COMPLETED = "completed";
/*      */   private static final String FN_COMPNUM = "comp";
/*      */   private static final String FN_COMMENT = "cmt";
/*      */   private static final String FN_CONTACT = "contact";
/*      */   private static final String FN_DESC = "desc";
/*      */   private static final String FN_DESC_HTML = "descH";
/*      */   private static final String FN_DESC_IN_META = "dinM";
/*      */   private static final String FN_FRAGMENT = "frag";
/*      */   private static final String FN_DTSTAMP = "dts";
/*      */   private static final String FN_DURATION = "duration";
/*      */   private static final String FN_END = "et";
/*      */   private static final String FN_APPT_FREEBUSY = "fb";
/*      */   private static final String FN_GEO = "geo";
/*      */   private static final String FN_LOCATION = "l";
/*      */   private static final String FN_LOCAL_ONLY = "lo";
/*      */   private static final String FN_INVMSGID = "mid";
/*      */   private static final String FN_LAST_MODIFIED = "lastMod";
/*      */   public static Invite createInvite(int mailboxId, MailItem.Type type, String method, TimeZoneMap tzMap, String uidOrNull, String status, String priority, String pctComplete, long completed, String freeBusy, String transparency, String classProp, boolean allDayEvent, ParsedDateTime dtStart, ParsedDateTime dtEndOrNull, ParsedDuration durationOrNull, RecurId recurId, Recurrence.IRecurrence recurrenceOrNull, boolean isOrganizer, ZOrganizer organizer, List<ZAttendee> attendees, String name, String location, String description, String descHtml, List<String> comments, List<String> categories, List<String> contacts, Geo geo, String url, long dtStamp, long lastModified, int seqNo, int lastFullSeqNo, String partStat, boolean rsvp, boolean sentByMe)
/*      */   {
/*  226 */     return new Invite(type, method, tzMap, null, uidOrNull, status, priority, pctComplete, completed, freeBusy, transparency, classProp, dtStart, dtEndOrNull, durationOrNull, recurrenceOrNull, isOrganizer, organizer, attendees, name, location, 0x2 | (allDayEvent ? 4 : 0), partStat, rsvp, recurId, dtStamp, lastModified, seqNo, lastFullSeqNo, mailboxId, 0, 0, sentByMe, description, descHtml, Fragment.getFragment(description, true), comments, categories, contacts, geo, url);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public void setInviteId(int invId)
/*      */   {
/*  242 */     this.mMailItemId = invId;
/*  243 */     if (this.mRecurrence != null) {
/*  244 */       this.mRecurrence.setInviteId(new InviteInfo(this));
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */   private static final String FN_METHOD = "mthd";
/*      */   
/*      */   private static final String FN_NAME = "n";
/*      */   
/*      */   private static final String FN_NUM_ATTENDEES = "numAt";
/*      */   
/*      */   private static final String FN_NUM_CATEGORIES = "numCat";
/*      */   
/*      */   private static final String FN_NUM_COMMENTS = "numCmt";
/*      */   
/*      */   private static final String FN_NUM_CONTACTS = "numContacts";
/*      */   
/*      */   private static final String FN_ORGANIZER = "org";
/*      */   
/*      */   private static final String FN_IS_ORGANIZER = "isOrg";
/*      */   
/*      */   private static final String FN_PARTSTAT = "ptst";
/*      */   
/*      */   private static final String FN_RSVP = "rsvp";
/*      */   
/*      */   private static final String FN_RECURRENCE = "recurrence";
/*      */   
/*      */   private static final String FN_RECUR_ID = "rid";
/*      */   
/*      */   private static final String FN_SEQ_NO = "seq";
/*      */   
/*      */   private static final String FN_LAST_FULL_SEQ_NO = "lfseq";
/*      */   
/*      */   private static final String FN_STATUS = "status";
/*      */   
/*      */   private static final String FN_START = "st";
/*      */   
/*      */   private static final String FN_TRANSP = "tr";
/*      */   
/*      */   private static final String FN_TZMAP = "tzm";
/*      */   
/*      */   private static final String FN_UID = "u";
/*      */   
/*      */   private static final String FN_PRIORITY = "prio";
/*      */   
/*      */   private static final String FN_PCT_COMPLETE = "pctcompl";
/*      */   
/*      */   private static final String FN_NUM_ALARMS = "numAl";
/*      */   
/*      */   private static final String FN_ALARM = "al";
/*      */   
/*      */   private static final String FN_DONT_INDEX_MM = "noidxmm";
/*      */   private static final String FN_URL = "url";
/*      */   private String mDescription;
/*      */   private String mDescHtml;
/*      */   public static int getMaxDescInMeta()
/*      */   {
/*  301 */     return LC.calendar_max_desc_in_metadata.intValueWithinRange(0, 1048576);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static Metadata encodeMetadata(Invite inv)
/*      */   {
/*  312 */     Metadata meta = new Metadata();
/*      */     
/*      */ 
/*      */ 
/*  316 */     if (inv.isLocalOnly()) {
/*  317 */       meta.put("lo", true);
/*      */     }
/*  319 */     meta.put("it", inv.getItemType().toByte());
/*  320 */     meta.put("u", inv.getUid());
/*  321 */     meta.put("mid", inv.getMailItemId());
/*  322 */     meta.put("comp", inv.getComponentNum());
/*  323 */     meta.put("byme", inv.mSentByMe);
/*  324 */     if (!inv.isPublic())
/*  325 */       meta.put("cl", inv.getClassProp());
/*  326 */     meta.put("clSetByMe", inv.classPropSetByMe());
/*  327 */     meta.put("status", inv.getStatus());
/*  328 */     if (inv.hasFreeBusy())
/*  329 */       meta.put("fb", inv.getFreeBusy());
/*  330 */     meta.put("tr", inv.getTransparency());
/*  331 */     meta.put("st", inv.mStart);
/*  332 */     meta.put("et", inv.mEnd);
/*  333 */     if (inv.mCompleted != 0L)
/*  334 */       meta.put("completed", inv.mCompleted);
/*  335 */     meta.put("duration", inv.mDuration);
/*  336 */     meta.put("mthd", inv.mMethod.toString());
/*  337 */     meta.put("frag", inv.mFragment);
/*      */     
/*      */ 
/*  340 */     if (inv.mDescInMeta) {
/*  341 */       meta.put("dinM", inv.mDescInMeta);
/*  342 */       if (inv.mDescription != null)
/*  343 */         meta.put("desc", inv.mDescription);
/*  344 */       if (inv.mDescHtml != null) {
/*  345 */         meta.put("descH", inv.mDescHtml);
/*      */       }
/*      */     }
/*  348 */     if (inv.mRecurrence != null) {
/*  349 */       meta.put("recurrence", inv.mRecurrence.encodeMetadata());
/*      */     }
/*      */     
/*  352 */     meta.put("n", inv.getName());
/*      */     
/*  354 */     meta.put("l", inv.mLocation);
/*  355 */     meta.put("af", inv.getFlags());
/*  356 */     meta.put("ptst", inv.getPartStat());
/*  357 */     meta.put("rsvp", inv.getRsvp());
/*      */     
/*  359 */     meta.put("tzm", Util.encodeAsMetadata(inv.mTzMap));
/*      */     
/*  361 */     if (inv.hasRecurId()) {
/*  362 */       meta.put("rid", inv.getRecurId().encodeMetadata());
/*      */     }
/*  364 */     meta.put("dts", inv.getDTStamp());
/*  365 */     if (inv.getLastModified() != 0L)
/*  366 */       meta.put("lastMod", inv.getLastModified());
/*  367 */     meta.put("seq", inv.getSeqNo());
/*  368 */     meta.put("lfseq", inv.getLastFullSeqNo());
/*      */     
/*  370 */     if (inv.hasOrganizer()) {
/*  371 */       meta.put("org", inv.getOrganizer().encodeMetadata());
/*      */     }
/*  373 */     meta.put("isOrg", inv.isOrganizer());
/*      */     
/*  375 */     List<ZAttendee> ats = inv.getAttendees();
/*  376 */     meta.put("numAt", String.valueOf(ats.size()));
/*  377 */     int i = 0;
/*  378 */     for (Iterator<ZAttendee> iter = ats.iterator(); iter.hasNext(); i++) {
/*  379 */       ZAttendee at = (ZAttendee)iter.next();
/*  380 */       meta.put("at" + i, at.encodeAsMetadata());
/*      */     }
/*      */     
/*  383 */     meta.put("prio", inv.getPriority());
/*  384 */     meta.put("pctcompl", inv.getPercentComplete());
/*      */     
/*  386 */     List<String> comments = inv.getComments();
/*  387 */     int idx; if (comments != null) {
/*  388 */       int numComm = comments.size();
/*  389 */       if (numComm > 0) {
/*  390 */         meta.put("numCmt", numComm);
/*  391 */         idx = 0;
/*  392 */         for (String comm : comments) {
/*  393 */           meta.put("cmt" + idx, comm);
/*  394 */           idx++;
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*  399 */     List<String> contacts = inv.getContacts();
/*  400 */     int idx; if (contacts != null) {
/*  401 */       int numContacts = contacts.size();
/*  402 */       if (numContacts > 0) {
/*  403 */         meta.put("numContacts", numContacts);
/*  404 */         idx = 0;
/*  405 */         for (String contact : contacts) {
/*  406 */           meta.put("contact" + idx, contact);
/*  407 */           idx++;
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*  412 */     List<String> categories = inv.getCategories();
/*  413 */     int idx; if (categories != null) {
/*  414 */       int numCat = categories.size();
/*  415 */       if (numCat > 0) {
/*  416 */         meta.put("numCat", numCat);
/*  417 */         idx = 0;
/*  418 */         for (String cat : categories) {
/*  419 */           meta.put("cat" + idx, cat);
/*  420 */           idx++;
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*  425 */     Geo geo = inv.getGeo();
/*  426 */     if (geo != null) {
/*  427 */       meta.put("geo", Util.encodeMetadata(geo));
/*      */     }
/*      */     
/*  430 */     String url = inv.getUrl();
/*  431 */     if ((url != null) && (url.length() > 0)) {
/*  432 */       meta.put("url", url);
/*      */     }
/*  434 */     if (!inv.mAlarms.isEmpty()) {
/*  435 */       meta.put("numAl", inv.mAlarms.size());
/*  436 */       i = 0;
/*  437 */       for (Iterator<Alarm> iter = inv.mAlarms.iterator(); iter.hasNext(); i++) {
/*  438 */         Alarm alarm = (Alarm)iter.next();
/*  439 */         meta.put("al" + i, alarm.encodeMetadata());
/*      */       }
/*      */     }
/*      */     
/*  443 */     if (inv.mXProps.size() > 0) {
/*  444 */       Util.encodeXPropsAsMetadata(meta, inv.xpropsIterator());
/*      */     }
/*  446 */     if (inv.mDontIndexMimeMessage)
/*  447 */       meta.put("noidxmm", true);
/*  448 */     return meta;
/*      */   }
/*      */   
/*      */   public static ZCalendar.ICalTok lookupMethod(String methodName)
/*      */   {
/*  453 */     String methodNameUpper = methodName.toUpperCase();
/*      */     ZCalendar.ICalTok toRet;
/*  455 */     try { toRet = ZCalendar.ICalTok.valueOf(methodNameUpper);
/*      */     } catch (IllegalArgumentException e) {
/*  457 */       toRet = ZCalendar.ICalTok.PUBLISH;
/*      */       
/*  459 */       if (methodNameUpper.compareToIgnoreCase("EXPORT") != 0) {
/*  460 */         sLog.warn("Invalid METHOD " + methodName + "; assuming PUBLISH", e);
/*      */       }
/*      */     }
/*  463 */     switch (toRet) {
/*      */     case REQUEST: 
/*      */     case PUBLISH: 
/*      */     case REPLY: 
/*      */     case ADD: 
/*      */     case CANCEL: 
/*      */     case REFRESH: 
/*      */     case COUNTER: 
/*      */     case DECLINECOUNTER: 
/*  472 */       return toRet;
/*      */     }
/*  474 */     return ZCalendar.ICalTok.PUBLISH;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static Invite decodeMetadata(int mailboxId, Metadata meta, CalendarItem calItem, ICalTimeZone accountTZ)
/*      */     throws ServiceException
/*      */   {
/*  491 */     byte btype = (byte)(int)meta.getLong("it", -1L);
/*  492 */     MailItem.Type type = btype >= 0 ? MailItem.Type.of(btype) : MailItem.Type.APPOINTMENT;
/*  493 */     String uid = meta.get("u", null);
/*  494 */     int mailItemId = (int)meta.getLong("mid");
/*  495 */     int componentNum = (int)meta.getLong("comp");
/*  496 */     String classProp = meta.get("cl", "PUB");
/*  497 */     boolean classPropSetByMe = meta.getBool("clSetByMe", false);
/*  498 */     String status = meta.get("status", "CONF");
/*  499 */     String freebusy = meta.get("fb", null);
/*  500 */     String transp = meta.get("tr", "O");
/*  501 */     boolean sentByMe = meta.getBool("byme");
/*  502 */     String fragment = meta.get("frag", "");
/*      */     
/*  504 */     boolean descInMeta = meta.getBool("dinM", false);
/*  505 */     String desc = descInMeta ? meta.get("desc", null) : null;
/*  506 */     String descHtml = descInMeta ? meta.get("descH", null) : null;
/*      */     
/*  508 */     long completed = meta.getLong("completed", 0L);
/*      */     
/*  510 */     ParsedDateTime dtStart = null;
/*  511 */     ParsedDateTime dtEnd = null;
/*  512 */     ParsedDuration duration = null;
/*      */     
/*  514 */     RecurId recurrenceId = null;
/*      */     
/*  516 */     TimeZoneMap tzMap = Util.decodeFromMetadata(meta.getMap("tzm"), accountTZ);
/*      */     
/*  518 */     Metadata metaRecur = meta.getMap("recurrence", true);
/*  519 */     Recurrence.IRecurrence recurrence = null;
/*  520 */     if (metaRecur != null) {
/*  521 */       recurrence = Recurrence.decodeMetadata(metaRecur, tzMap);
/*      */     }
/*      */     
/*  524 */     String methodStr = meta.get("mthd", ZCalendar.ICalTok.PUBLISH.toString());
/*  525 */     if (ZCalendar.ICalTok.CANCEL.toString().equals(methodStr)) {
/*  526 */       status = "CANC";
/*      */     }
/*  528 */     int flags = (int)meta.getLong("af", 0L);
/*      */     try
/*      */     {
/*  531 */       dtStart = ParsedDateTime.parse(meta.get("st", null), tzMap);
/*      */       
/*  533 */       dtEnd = ParsedDateTime.parse(meta.get("et", null), tzMap);
/*  534 */       if ((flags & 0x4) != 0)
/*      */       {
/*  536 */         if (dtStart != null)
/*  537 */           dtStart.forceDateOnly();
/*  538 */         if (dtEnd != null) {
/*  539 */           dtEnd.forceDateOnly();
/*      */         }
/*      */       }
/*  542 */       duration = ParsedDuration.parse(meta.get("duration", null));
/*      */       
/*  544 */       if (meta.containsKey("rid")) {
/*  545 */         Metadata rdata = meta.getMap("rid");
/*      */         
/*  547 */         recurrenceId = RecurId.decodeMetadata(rdata, tzMap);
/*      */       }
/*      */     }
/*      */     catch (java.text.ParseException e) {
/*  551 */       throw ServiceException.FAILURE(String.format("Error parsing metadata for invite %s-%s in calItem %s", new Object[] { Integer.valueOf(mailItemId), Integer.valueOf(componentNum), calItem != null ? Integer.toString(calItem.getId()) : "(null)" }), e);
/*      */     }
/*      */     
/*      */ 
/*  555 */     String name = meta.get("n", "");
/*  556 */     String loc = meta.get("l", null);
/*      */     
/*      */ 
/*  559 */     String partStat = meta.get("ptst", "AC");
/*      */     
/*  561 */     boolean rsvp = meta.getBool("rsvp", true);
/*  562 */     long dtstamp = meta.getLong("dts", 0L);
/*  563 */     long lastModified = meta.getLong("lastMod", 0L);
/*  564 */     int seqno = (int)meta.getLong("seq", 0L);
/*  565 */     int lastFullSeqno = (int)meta.getLong("lfseq", seqno);
/*      */     
/*  567 */     ZOrganizer org = null;
/*      */     try {
/*  569 */       Metadata metaOrg = meta.getMap("org", true);
/*  570 */       org = metaOrg != null ? new ZOrganizer(metaOrg) : null;
/*      */     } catch (ServiceException e) {
/*  572 */       sLog.warn("Problem decoding organizer for calItem %s invite %s-%s", new Object[] { calItem != null ? Integer.toString(calItem.getId()) : "(null)", Integer.valueOf(mailItemId), Integer.valueOf(componentNum) });
/*      */     }
/*      */     
/*      */ 
/*  576 */     long numAts = meta.getLong("numAt", 0L);
/*  577 */     ArrayList<ZAttendee> attendees = new ArrayList((int)numAts);
/*  578 */     for (int i = 0; i < numAts; i++) {
/*      */       try {
/*  580 */         Metadata metaAttendee = meta.getMap("at" + i, true);
/*  581 */         if (metaAttendee != null)
/*  582 */           attendees.add(new ZAttendee(metaAttendee));
/*      */       } catch (ServiceException e) {
/*  584 */         ZimbraLog.calendar.warn("Problem decoding attendee %s for calendar item %s invite %s-%s", new Object[] { Integer.valueOf(i), calItem != null ? Integer.toString(calItem.getId()) : "(null)", Integer.valueOf(mailItemId), Integer.valueOf(componentNum) });
/*      */       }
/*      */     }
/*      */     
/*      */ 
/*  589 */     boolean isOrganizer = false;
/*  590 */     if (meta.containsKey("isOrg")) {
/*  591 */       isOrganizer = meta.getBool("isOrg");
/*      */ 
/*      */     }
/*  594 */     else if (org != null) {
/*  595 */       String orgAddr = org.getAddress();
/*  596 */       Account account = MailboxManager.getInstance().getMailboxById(mailboxId).getAccount();
/*  597 */       AccountUtil.AccountAddressMatcher acctMatcher = new AccountUtil.AccountAddressMatcher(account);
/*  598 */       isOrganizer = acctMatcher.matches(orgAddr);
/*      */ 
/*      */     }
/*      */     else
/*      */     {
/*  603 */       isOrganizer = numAts < 1L;
/*      */     }
/*      */     
/*      */ 
/*  607 */     String priority = meta.get("prio", null);
/*  608 */     String pctComplete = meta.get("pctcompl", null);
/*      */     
/*  610 */     List<String> comments = null;
/*  611 */     int numComm = (int)meta.getLong("numCmt", 0L);
/*  612 */     if (numComm > 0) {
/*  613 */       comments = new ArrayList(numComm);
/*  614 */       for (int i = 0; i < numComm; i++) {
/*  615 */         String comm = meta.get("cmt" + i, null);
/*  616 */         if (comm != null) {
/*  617 */           comments.add(comm);
/*      */         }
/*      */       }
/*      */     }
/*  621 */     List<String> contacts = null;
/*  622 */     int numContacts = (int)meta.getLong("numContacts", 0L);
/*  623 */     if (numContacts > 0) {
/*  624 */       contacts = new ArrayList(numContacts);
/*  625 */       for (int i = 0; i < numContacts; i++) {
/*  626 */         String contact = meta.get("contact" + i, null);
/*  627 */         if (contact != null) {
/*  628 */           contacts.add(contact);
/*      */         }
/*      */       }
/*      */     }
/*  632 */     List<String> categories = null;
/*  633 */     int numCat = (int)meta.getLong("numCat", 0L);
/*  634 */     if (numCat > 0) {
/*  635 */       categories = new ArrayList(numCat);
/*  636 */       for (int i = 0; i < numCat; i++) {
/*  637 */         String cat = meta.get("cat" + i, null);
/*  638 */         if (cat != null) {
/*  639 */           categories.add(cat);
/*      */         }
/*      */       }
/*      */     }
/*  643 */     Geo geo = null;
/*  644 */     Metadata metaGeo = meta.getMap("geo", true);
/*  645 */     if (metaGeo != null) {
/*  646 */       geo = Util.decodeGeoFromMetadata(metaGeo);
/*      */     }
/*  648 */     String url = meta.get("url", null);
/*      */     
/*  650 */     Invite invite = new Invite(type, methodStr, tzMap, calItem, uid, status, priority, pctComplete, completed, freebusy, transp, classProp, dtStart, dtEnd, duration, recurrence, isOrganizer, org, attendees, name, loc, flags, partStat, rsvp, recurrenceId, dtstamp, lastModified, seqno, lastFullSeqno, mailboxId, mailItemId, componentNum, sentByMe, desc, descHtml, fragment, comments, categories, contacts, geo, url);
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*  655 */     invite.mDescInMeta = descInMeta;
/*      */     
/*  657 */     invite.setClassPropSetByMe(classPropSetByMe);
/*      */     
/*  659 */     long numAlarms = meta.getLong("numAl", 0L);
/*  660 */     for (int i = 0; i < numAlarms; i++) {
/*      */       try {
/*  662 */         Metadata metaAlarm = meta.getMap("al" + i, true);
/*  663 */         if (metaAlarm != null) {
/*  664 */           Alarm alarm = Alarm.decodeMetadata(metaAlarm);
/*  665 */           if (alarm != null)
/*  666 */             invite.addAlarm(alarm);
/*      */         }
/*      */       } catch (ServiceException e) {
/*  669 */         ZimbraLog.calendar.warn("Problem decoding alarm %s for calendar item %s invite %s-%s", Integer.valueOf(i), calItem != null ? Integer.toString(calItem.getId()) : "(null)", Integer.valueOf(mailItemId), Integer.valueOf(componentNum), e);
/*      */       }
/*      */     }
/*      */     
/*      */ 
/*      */ 
/*  675 */     List<ZCalendar.ZProperty> xprops = Util.decodeXPropsFromMetadata(meta);
/*  676 */     if (xprops != null) {
/*  677 */       for (ZCalendar.ZProperty xprop : xprops) {
/*  678 */         boolean isHtmlDesc = false;
/*  679 */         if (ZCalendar.ICalTok.X_ALT_DESC.equals(xprop.getToken()))
/*      */         {
/*      */ 
/*  682 */           ZCalendar.ZParameter fmttype = xprop.getParameter(ZCalendar.ICalTok.FMTTYPE);
/*  683 */           if ((fmttype != null) && ("text/html".equalsIgnoreCase(fmttype.getValue()))) {
/*  684 */             isHtmlDesc = true;
/*  685 */             invite.mDescHtml = xprop.getValue();
/*      */           }
/*      */         }
/*  688 */         if (!isHtmlDesc) {
/*  689 */           invite.addXProp(xprop);
/*      */         }
/*      */       }
/*      */     }
/*  693 */     invite.setDontIndexMimeMessage(meta.getBool("noidxmm", false));
/*      */     
/*  695 */     boolean localOnly = meta.getBool("lo", false);
/*  696 */     invite.setLocalOnly(localOnly);
/*      */     
/*  698 */     invite.sanitize(false);
/*  699 */     return invite;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*  705 */   private boolean mDescInMeta = true;
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  714 */   private boolean mDontIndexMimeMessage = false;
/*      */   
/*  716 */   public synchronized void setDontIndexMimeMessage(boolean truthiness) { this.mDontIndexMimeMessage = truthiness; }
/*  717 */   public synchronized boolean getDontIndexMimeMessage() { return this.mDontIndexMimeMessage; }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public boolean descInMeta()
/*      */   {
/*  725 */     return this.mDescInMeta;
/*      */   }
/*      */   
/*      */ 
/*      */   public boolean hasBlobPart()
/*      */   {
/*  731 */     return (!descInMeta()) || (hasAttachment());
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public synchronized String getDescription()
/*      */     throws ServiceException
/*      */   {
/*  746 */     if ((!this.mDescInMeta) && (this.mDescription == null))
/*  747 */       loadDescFromBlob();
/*  748 */     return this.mDescription;
/*      */   }
/*      */   
/*      */   public synchronized String getDescriptionHtml() throws ServiceException {
/*  752 */     if ((!this.mDescInMeta) && (this.mDescHtml == null))
/*  753 */       loadDescFromBlob();
/*  754 */     return this.mDescHtml;
/*      */   }
/*      */   
/*      */   private synchronized void loadDescFromBlob() throws ServiceException {
/*  758 */     MimeMessage mmInv = this.mCalItem != null ? this.mCalItem.getSubpartMessage(this.mMailItemId) : null;
/*  759 */     if (mmInv != null) {
/*  760 */       this.mDescription = getDescription(mmInv, "text/plain");
/*  761 */       this.mDescHtml = getDescription(mmInv, "text/html");
/*      */     }
/*      */   }
/*      */   
/*      */   public synchronized void setDescription(String desc, String html) {
/*  766 */     int maxInMeta = getMaxDescInMeta();
/*  767 */     boolean shortDesc = (desc == null) || (desc.length() <= maxInMeta);
/*  768 */     boolean shortHtml = (html == null) || (html.length() <= maxInMeta * 3);
/*  769 */     this.mDescInMeta = ((shortDesc) && (shortHtml));
/*  770 */     this.mDescription = desc;
/*  771 */     this.mDescHtml = html;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static String getDescription(Part mmInv, String mimeType)
/*      */     throws ServiceException
/*      */   {
/*  783 */     if (mmInv == null) { return null;
/*      */     }
/*      */     try
/*      */     {
/*  787 */       String mmCtStr = mmInv.getContentType();
/*  788 */       if (mmCtStr != null) {
/*  789 */         ContentType mmCt = new ContentType(mmCtStr);
/*  790 */         if (mmCt.match("text/calendar")) {
/*  791 */           boolean wantHtml = "text/html".equalsIgnoreCase(mimeType);
/*  792 */           Object mmInvContent = mmInv.getContent();
/*  793 */           InputStream is = null;
/*      */           try {
/*  795 */             String charset = "utf-8";
/*  796 */             if ((mmInvContent instanceof InputStream)) {
/*  797 */               charset = mmCt.getParameter("charset");
/*  798 */               if (charset == null)
/*  799 */                 charset = "utf-8";
/*  800 */               is = (InputStream)mmInvContent;
/*  801 */             } else if ((mmInvContent instanceof String)) {
/*  802 */               String str = (String)mmInvContent;
/*  803 */               charset = "utf-8";
/*  804 */               is = new ByteArrayInputStream(str.getBytes(charset));
/*      */             }
/*  806 */             if (is != null) {
/*  807 */               ZCalendar.ZVCalendar iCal = ZCalendar.ZCalendarBuilder.build(is, charset);
/*  808 */               for (compIter = iCal.getComponentIterator(); compIter.hasNext();) {
/*  809 */                 ZCalendar.ZComponent component = (ZCalendar.ZComponent)compIter.next();
/*  810 */                 ZCalendar.ICalTok compTypeTok = component.getTok();
/*  811 */                 if ((compTypeTok == ZCalendar.ICalTok.VEVENT) || (compTypeTok == ZCalendar.ICalTok.VTODO)) { String str1;
/*  812 */                   if (!wantHtml) {
/*  813 */                     return component.getPropVal(ZCalendar.ICalTok.DESCRIPTION, null);
/*      */                   }
/*  815 */                   return component.getDescriptionHtml();
/*      */                 }
/*      */               }
/*      */             }
/*      */           } finally { Iterator<ZCalendar.ZComponent> compIter;
/*  820 */             ByteUtil.closeStream(is);
/*      */           }
/*      */         }
/*      */       }
/*      */       
/*  825 */       Object mmInvContent = mmInv.getContent();
/*  826 */       if (!(mmInvContent instanceof MimeMultipart)) {
/*  827 */         if ((mmInvContent instanceof InputStream)) {
/*  828 */           ByteUtil.closeStream((InputStream)mmInvContent);
/*      */         }
/*  830 */         return null;
/*      */       }
/*  832 */       MimeMultipart mm = (MimeMultipart)mmInvContent;
/*      */       
/*      */ 
/*  835 */       int numParts = mm.getCount();
/*  836 */       String charset = null;
/*  837 */       for (int i = 0; i < numParts; i++) {
/*  838 */         BodyPart part = mm.getBodyPart(i);
/*  839 */         String ctStr = part.getContentType();
/*      */         try {
/*  841 */           ContentType ct = new ContentType(ctStr);
/*  842 */           if (ct.match(mimeType)) {
/*  843 */             charset = ct.getParameter("charset");
/*  844 */             if (charset == null) charset = "us-ascii";
/*  845 */             byte[] descBytes = ByteUtil.getContent(part.getInputStream(), part.getSize());
/*  846 */             return new String(descBytes, charset);
/*      */           }
/*      */           
/*  849 */           if (ct.getBaseType().matches("multipart/.*")) {
/*  850 */             String str = getDescription(part, mimeType);
/*  851 */             if (str != null) {
/*  852 */               return str;
/*      */             }
/*      */           }
/*      */         } catch (javax.mail.internet.ParseException e) {
/*  856 */           ZimbraLog.calendar.warn("Invalid Content-Type found: \"" + ctStr + "\"; skipping part", e);
/*      */         }
/*      */       }
/*      */     } catch (IOException e) {
/*  860 */       throw ServiceException.FAILURE("Unable to get calendar item notes MIME part", e);
/*      */     } catch (MessagingException e) {
/*  862 */       throw ServiceException.FAILURE("Unable to get calendar item notes MIME part", e);
/*      */     }
/*  864 */     return null;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public MimeMessage getMimeMessage()
/*      */     throws ServiceException
/*      */   {
/*  874 */     if ((this.mCalItem == null) || (this.mMailItemId <= 0)) return null;
/*  875 */     return this.mCalItem.getSubpartMessage(this.mMailItemId);
/*      */   }
/*      */   
/*  878 */   public void setPartStat(String partStat) { this.mPartStat = partStat; }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public void updateMyPartStat(Account acct, String partStat)
/*      */     throws ServiceException
/*      */   {
/*  887 */     if (this.mIsOrganizer) {
/*  888 */       setPartStat("AC");
/*  889 */       setRsvp(false);
/*      */     } else {
/*  891 */       ZAttendee at = getMatchingAttendee(acct);
/*  892 */       if (at != null) {
/*  893 */         setRsvp(at.hasRsvp() ? at.getRsvp().booleanValue() : false);
/*      */         
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  899 */         if ((this.mMethod == ZCalendar.ICalTok.REQUEST) || (this.mMethod == ZCalendar.ICalTok.COUNTER)) {
/*  900 */           setPartStat(partStat);
/*  901 */           at.setPartStat(partStat);
/*      */         }
/*      */       }
/*      */       else
/*      */       {
/*  906 */         setRsvp(true);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public CalendarItem getCalendarItem()
/*      */   {
/*  915 */     return this.mCalItem;
/*      */   }
/*      */   
/*      */   public void setCalendarItem(CalendarItem calItem) {
/*  919 */     this.mCalItem = calItem;
/*      */   }
/*      */   
/*      */   public void setIsAllDayEvent(boolean allDayEvent) {
/*  923 */     if (allDayEvent) {
/*  924 */       this.mFlags |= 0x4;
/*      */     } else
/*  926 */       this.mFlags &= 0xFFFFFFFB;
/*      */   }
/*      */   
/*  929 */   public int getComponentNum() { return this.mComponentNum; }
/*  930 */   public void setComponentNum(int num) { this.mComponentNum = num; }
/*  931 */   public int getMailboxId() { return this.mMailboxId; }
/*  932 */   void setMailboxId(int id) { this.mMailboxId = id; }
/*  933 */   public int getMailItemId() { return this.mMailItemId; }
/*  934 */   public void setMailItemId(int id) { this.mMailItemId = id; }
/*  935 */   public int getFlags() { return this.mFlags; }
/*  936 */   public void setFlags(int flags) { this.mFlags = flags; }
/*  937 */   public String getPartStat() { return this.mPartStat; }
/*  938 */   public boolean getRsvp() { return this.mRsvp; }
/*  939 */   public void setRsvp(boolean rsvp) { this.mRsvp = rsvp; }
/*  940 */   public String getUid() { return this.mUid; }
/*  941 */   public void setUid(String uid) { this.mUid = uid; }
/*  942 */   public String getName() { return this.mName; }
/*  943 */   public void setName(String name) { this.mName = name; }
/*  944 */   public String getStatus() { return this.mStatus; }
/*  945 */   public void setStatus(String status) { this.mStatus = status; }
/*  946 */   public boolean hasFreeBusy() { return this.mFreeBusy != null; }
/*  947 */   public String getFreeBusy() { return this.mFreeBusy != null ? this.mFreeBusy : "B"; }
/*  948 */   public void setFreeBusy(String fb) { this.mFreeBusy = fb; }
/*  949 */   public String getTransparency() { return this.mTransparency; }
/*  950 */   public boolean isTransparent() { return "T".equals(this.mTransparency); }
/*  951 */   public void setTransparency(String transparency) { this.mTransparency = transparency; }
/*  952 */   public String getClassProp() { return this.mClass; }
/*  953 */   public void setClassProp(String classProp) { this.mClass = classProp; }
/*  954 */   public boolean classPropSetByMe() { return this.mClassSetByMe; }
/*  955 */   public void setClassPropSetByMe(boolean b) { this.mClassSetByMe = b; }
/*  956 */   public long getCompleted() { return this.mCompleted; }
/*  957 */   public void setCompleted(long completed) { this.mCompleted = completed; }
/*  958 */   public int getSeqNo() { return this.mSeqNo; }
/*  959 */   public int getLastFullSeqNo() { return this.mLastFullSeqNo; }
/*  960 */   public void setSeqNo(int seqNo) { this.mSeqNo = seqNo; }
/*  961 */   public void setLastFullSeqNo(int seqNo) { this.mLastFullSeqNo = seqNo; }
/*  962 */   public ParsedDateTime getStartTime() { return this.mStart; }
/*  963 */   public void setDtStart(ParsedDateTime dtStart) { this.mStart = dtStart; }
/*  964 */   public ParsedDateTime getEndTime() { return this.mEnd; }
/*  965 */   public void setDtEnd(ParsedDateTime dtend) { this.mEnd = dtend; }
/*  966 */   public ParsedDuration getDuration() { return this.mDuration; }
/*  967 */   public void setDuration(ParsedDuration dur) { this.mDuration = dur; }
/*  968 */   public String getPriority() { return this.mPriority; }
/*  969 */   public void setPriority(String prio) { this.mPriority = prio; }
/*  970 */   public String getPercentComplete() { return this.mPercentComplete; }
/*  971 */   public void setPercentComplete(String pct) { this.mPercentComplete = pct; }
/*  972 */   public List<String> getCategories() { return this.mCategories; }
/*  973 */   public void addCategory(String category) { this.mCategories.add(category); }
/*  974 */   public List<String> getContacts() { return this.mContacts; }
/*  975 */   public void addContact(String contact) { this.mContacts.add(contact); }
/*  976 */   public List<String> getComments() { return this.mComments; }
/*  977 */   public void addComment(String comment) { this.mComments.add(comment); }
/*  978 */   public Geo getGeo() { return this.mGeo; }
/*  979 */   public void setGeo(Geo geo) { this.mGeo = geo; }
/*  980 */   public String getUrl() { return this.mUrl; }
/*  981 */   public void setUrl(String url) { this.mUrl = (url != null ? url : ""); }
/*      */   
/*  983 */   public long getDTStamp() { return this.mDTStamp; }
/*      */   
/*  985 */   public void setDtStamp(long stamp) { this.mDTStamp = (stamp / 1000L * 1000L);
/*  986 */     if (this.mLastModified == 0L)
/*  987 */       setLastModified(this.mDTStamp); }
/*      */   
/*  989 */   public long getLastModified() { return this.mLastModified; }
/*      */   
/*  991 */   public void setLastModified(long lastModified) { this.mLastModified = (lastModified / 1000L * 1000L); }
/*      */   
/*      */   public boolean isPublic()
/*      */   {
/*  995 */     return "PUB".equals(this.mClass);
/*      */   }
/*      */   
/*      */   public boolean isCancel() {
/*  999 */     return (ZCalendar.ICalTok.CANCEL.toString().equals(this.mMethod)) || ("CANC".equals(this.mStatus));
/*      */   }
/*      */   
/*      */   public String getFreeBusyActual()
/*      */   {
/* 1004 */     return partStatToFreeBusyActual(this.mPartStat);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public String partStatToFreeBusyActual(String partStat)
/*      */   {
/* 1017 */     String fb = getFreeBusy();
/*      */     
/*      */ 
/*      */ 
/* 1021 */     if ("F".equals(fb)) {
/* 1022 */       return "F";
/*      */     }
/*      */     
/* 1025 */     if ("AC".equals(partStat)) {
/* 1026 */       return fb;
/*      */     }
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/* 1034 */     if (("NE".equals(partStat)) || ("TE".equals(partStat)) || ("TENT".equals(this.mStatus)))
/*      */     {
/*      */ 
/* 1037 */       return "T";
/*      */     }
/*      */     
/*      */ 
/* 1041 */     if (("DE".equals(partStat)) || ("DG".equals(partStat)) || ("CANC".equals(this.mStatus)))
/*      */     {
/*      */ 
/* 1044 */       return "F";
/*      */     }
/* 1046 */     return fb;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public ParsedDateTime getEffectiveEndTime()
/*      */   {
/* 1057 */     if (this.mEnd != null)
/* 1058 */       return this.mEnd;
/* 1059 */     if (this.mStart == null)
/* 1060 */       return null;
/* 1061 */     ParsedDuration dur = this.mDuration;
/* 1062 */     if (dur == null) {
/* 1063 */       if (isTodo())
/* 1064 */         return null;
/* 1065 */       if (!this.mStart.hasTime()) {
/* 1066 */         dur = ParsedDuration.ONE_DAY;
/*      */       } else
/* 1068 */         dur = ParsedDuration.ONE_SECOND;
/*      */     }
/* 1070 */     return this.mStart.add(dur);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public ParsedDuration getEffectiveDuration()
/*      */   {
/* 1082 */     if (this.mDuration != null)
/* 1083 */       return this.mDuration;
/* 1084 */     if (this.mStart == null)
/* 1085 */       return null;
/* 1086 */     if (this.mEnd != null) {
/* 1087 */       return this.mEnd.difference(this.mStart);
/*      */     }
/* 1089 */     if (isTodo())
/* 1090 */       return null;
/* 1091 */     if (!this.mStart.hasTime()) {
/* 1092 */       return ParsedDuration.ONE_DAY;
/*      */     }
/* 1094 */     return ParsedDuration.ONE_SECOND;
/*      */   }
/*      */   
/*      */   public String getEffectivePartStat() throws ServiceException {
/* 1098 */     if (this.mCalItem == null) return getPartStat();
/* 1099 */     CalendarItem.Instance inst = isRecurrence() ? null : CalendarItem.Instance.fromInvite(this.mCalItem.getId(), this);
/* 1100 */     return this.mCalItem.getEffectivePartStat(this, inst);
/*      */   }
/*      */   
/* 1103 */   public String getLocation() { return this.mLocation; }
/* 1104 */   public void setLocation(String location) { this.mLocation = location; }
/* 1105 */   public boolean isAllDayEvent() { return (this.mFlags & 0x4) != 0; }
/* 1106 */   public boolean hasOrganizer() { return this.mOrganizer != null; }
/*      */   
/* 1108 */   public boolean hasOtherAttendees() { return (this.mAttendees != null) && (this.mAttendees.size() > 0); }
/*      */   
/*      */   void setIsRecurrence(boolean isRecurrence) {
/* 1111 */     if (isRecurrence) {
/* 1112 */       this.mFlags |= 0x20;
/*      */     } else
/* 1114 */       this.mFlags &= 0xFFFFFFDF;
/*      */   }
/*      */   
/* 1117 */   public boolean isRecurrence() { return (this.mFlags & 0x20) != 0; }
/*      */   
/*      */   public boolean hasAlarm() {
/* 1120 */     return !this.mAlarms.isEmpty();
/*      */   }
/*      */   
/* 1123 */   private List<Attach> attaches = null;
/*      */   public static final int APPT_FLAG_TODO = 1;
/*      */   public static final int APPT_FLAG_EVENT = 2;
/*      */   public static final int APPT_FLAG_ALLDAY = 4;
/*      */   public static final int APPT_FLAG_HASALARM = 16;
/*      */   
/* 1129 */   public List<Attach> getIcalendarAttaches() { return this.attaches != null ? this.attaches : new ArrayList(); }
/*      */   
/*      */   public void addIcalendarAttach(Attach attach)
/*      */   {
/* 1133 */     if (this.attaches == null) {
/* 1134 */       this.attaches = Lists.newArrayList();
/* 1135 */       setHasAttachment(true);
/*      */     }
/* 1137 */     this.attaches.add(attach);
/*      */   }
/*      */   
/* 1140 */   public boolean hasAttachment() { return (this.mFlags & 0x80) != 0; }
/*      */   
/* 1142 */   public void setHasAttachment(boolean hasAttachment) { if (hasAttachment) {
/* 1143 */       this.mFlags |= 0x80;
/*      */     } else {
/* 1145 */       this.mFlags &= 0xFF7F;
/*      */     }
/*      */   }
/*      */   
/* 1149 */   public boolean isDraft() { return (this.mFlags & 0x100) != 0; }
/*      */   
/* 1151 */   public void setDraft(boolean draft) { if (draft) {
/* 1152 */       this.mFlags |= 0x100;
/*      */     } else {
/* 1154 */       this.mFlags &= 0xFEFF;
/*      */     }
/*      */   }
/*      */   
/* 1158 */   public boolean isNeverSent() { return (this.mFlags & 0x200) != 0; }
/*      */   
/* 1160 */   public void setNeverSent(boolean neverSent) { if (neverSent) {
/* 1161 */       this.mFlags |= 0x200;
/*      */     } else {
/* 1163 */       this.mFlags &= 0xFDFF;
/*      */     }
/*      */   }
/*      */   
/*      */   public String toString()
/*      */   {
/* 1169 */     StringBuilder sb = new StringBuilder();
/* 1170 */     sb.append("{ ");
/* 1171 */     sb.append("mboxid: ").append(this.mMailboxId);
/* 1172 */     sb.append(", mailitem: ").append(this.mMailItemId);
/* 1173 */     sb.append(", compnum: ").append(this.mComponentNum);
/* 1174 */     sb.append(", uid: ").append(this.mUid);
/* 1175 */     sb.append(", status: ").append(getStatus());
/* 1176 */     sb.append(", partStat: ").append(getPartStat());
/* 1177 */     sb.append(", rsvp: ").append(getRsvp());
/* 1178 */     sb.append(", freeBusy: ").append(this.mFreeBusy);
/* 1179 */     sb.append(", transp: ").append(getTransparency());
/* 1180 */     sb.append(", class: ").append(getClassProp());
/* 1181 */     sb.append(", classSetByMe: ").append(classPropSetByMe());
/* 1182 */     sb.append(", sentByMe: ").append(sentByMe());
/* 1183 */     sb.append(", start: ").append(this.mStart);
/* 1184 */     sb.append(", end: ").append(this.mEnd);
/* 1185 */     sb.append(", duration: ").append(this.mDuration);
/* 1186 */     sb.append(", organizer: ");
/* 1187 */     if (hasOrganizer()) {
/* 1188 */       sb.append(getOrganizer().getAddress());
/*      */     } else
/* 1190 */       sb.append("(not specified)");
/* 1191 */     sb.append(", name: ").append(this.mName);
/* 1192 */     sb.append(", location: ").append(this.mLocation);
/* 1193 */     sb.append(", allDay: ").append(isAllDayEvent());
/* 1194 */     sb.append(", otherAts: ").append(hasOtherAttendees());
/* 1195 */     sb.append(", hasAlarm: ").append(hasAlarm());
/* 1196 */     sb.append(", isRecur: ").append(isRecurrence());
/* 1197 */     sb.append(", recurId: ").append(getRecurId());
/* 1198 */     sb.append(", DTStamp: ").append(this.mDTStamp);
/* 1199 */     sb.append(", lastMod: ").append(this.mLastModified);
/* 1200 */     sb.append(", mSeqNo ").append(this.mSeqNo);
/* 1201 */     sb.append(", mLastFullSeqNo ").append(this.mLastFullSeqNo);
/* 1202 */     if (isDraft())
/* 1203 */       sb.append(", draft: ").append(true);
/* 1204 */     if (isNeverSent()) {
/* 1205 */       sb.append(", neverSent: ").append(true);
/*      */     }
/* 1207 */     for (Alarm alarm : this.mAlarms) {
/* 1208 */       sb.append(", alarm: ").append(alarm.toString());
/*      */     }
/*      */     
/* 1211 */     for (ZCalendar.ZProperty xprop : this.mXProps) {
/* 1212 */       sb.append(", ").append(xprop.toString());
/*      */     }
/*      */     
/* 1215 */     sb.append("}");
/* 1216 */     return sb.toString();
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public static final int APPT_FLAG_ISRECUR = 32;
/*      */   
/*      */ 
/*      */   public static final int APPT_FLAG_NEEDS_REPLY = 64;
/*      */   
/*      */ 
/*      */   public static final int APPT_FLAG_HAS_ATTACHMENT = 128;
/*      */   
/*      */ 
/*      */   public static final int APPT_FLAG_DRAFT = 256;
/*      */   
/*      */   public static final int APPT_FLAG_NEVER_SENT = 512;
/*      */   
/* 1234 */   protected CalendarItem mCalItem = null;
/*      */   
/*      */   protected String mUid;
/*      */   
/* 1238 */   protected String mStatus = "CONF";
/* 1239 */   protected String mFreeBusy = null;
/* 1240 */   protected String mTransparency = "O";
/* 1241 */   protected String mClass = "PUB";
/*      */   protected boolean mClassSetByMe;
/* 1243 */   protected ParsedDateTime mStart = null;
/* 1244 */   protected ParsedDateTime mEnd = null;
/* 1245 */   protected ParsedDuration mDuration = null;
/* 1246 */   protected long mCompleted = 0L;
/*      */   
/*      */   protected String mName;
/*      */   protected String mLocation;
/* 1250 */   protected int mFlags = 2;
/* 1251 */   protected long mDTStamp = 0L;
/* 1252 */   protected long mLastModified = 0L;
/* 1253 */   protected int mSeqNo = 0;
/* 1254 */   protected int mLastFullSeqNo = 0;
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/* 1260 */   protected String mPartStat = "NE";
/*      */   
/* 1262 */   protected boolean mRsvp = false;
/*      */   
/*      */ 
/* 1265 */   protected int mMailboxId = 0;
/* 1266 */   protected int mMailItemId = 0;
/* 1267 */   protected int mComponentNum = 0;
/*      */   
/* 1269 */   private List<ZAttendee> mAttendees = new ArrayList();
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   private ZOrganizer mOrganizer;
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   private boolean mIsOrganizer;
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/* 1305 */   private boolean mLocalOnly = true;
/*      */   
/*      */   private String mPriority;
/*      */   
/*      */   private String mPercentComplete;
/* 1310 */   private List<String> mCategories = new ArrayList();
/* 1311 */   private List<String> mContacts = new ArrayList();
/* 1312 */   private List<String> mComments = new ArrayList();
/*      */   
/*      */   private Geo mGeo;
/*      */   
/*      */   private String mUrl;
/*      */   
/* 1318 */   private MailItem.Type type = MailItem.Type.APPOINTMENT;
/*      */   
/*      */   private ZCalendar.ICalTok mMethod;
/*      */   
/* 1322 */   private final List<Alarm> mAlarms = new ArrayList();
/*      */   
/* 1324 */   private final List<ZCalendar.ZProperty> mXProps = new ArrayList();
/*      */   private final TimeZoneMap mTzMap;
/*      */   
/* 1327 */   public Invite(String method, TimeZoneMap tzMap, boolean isOrganizer) { setItemType(MailItem.Type.APPOINTMENT);
/* 1328 */     this.mMethod = lookupMethod(method);
/* 1329 */     if (ZCalendar.ICalTok.CANCEL.equals(this.mMethod))
/* 1330 */       this.mStatus = "CANC";
/* 1331 */     this.mTzMap = tzMap;
/* 1332 */     this.mIsOrganizer = isOrganizer;
/* 1333 */     this.mFragment = "";
/*      */   }
/*      */   
/*      */   public Invite(MailItem.Type type, String method, TimeZoneMap tzMap, boolean isOrganizer) {
/* 1337 */     setItemType(type);
/* 1338 */     this.mMethod = lookupMethod(method);
/* 1339 */     if (ZCalendar.ICalTok.CANCEL.equals(this.mMethod)) {
/* 1340 */       this.mStatus = "CANC";
/*      */     }
/* 1342 */     this.mTzMap = tzMap;
/* 1343 */     this.mIsOrganizer = isOrganizer;
/* 1344 */     this.mFragment = "";
/*      */   }
/*      */   
/*      */ 
/* 1348 */   public String getMethod() { return this.mMethod.toString(); }
/* 1349 */   public void setMethod(String methodStr) { this.mMethod = lookupMethod(methodStr); }
/*      */   
/* 1351 */   public boolean sentByMe() { return this.mSentByMe; }
/* 1352 */   public void setSentByMe(boolean sentByMe) { this.mSentByMe = sentByMe; }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   private boolean thisAcctIsOrganizer(Account acct)
/*      */     throws ServiceException
/*      */   {
/* 1360 */     if (hasOrganizer()) {
/* 1361 */       AccountUtil.AccountAddressMatcher acctMatcher = new AccountUtil.AccountAddressMatcher(acct);
/* 1362 */       String addr = getOrganizer().getAddress();
/* 1363 */       boolean isOrg = acctMatcher.matches(addr);
/* 1364 */       if ((!isOrg) && (acct != null))
/*      */       {
/* 1366 */         String prefFromAddr = acct.getPrefFromAddress();
/* 1367 */         if ((prefFromAddr != null) && (prefFromAddr.equalsIgnoreCase(addr)))
/* 1368 */           isOrg = true;
/*      */       }
/* 1370 */       return isOrg;
/*      */     }
/*      */     
/*      */ 
/*      */ 
/* 1375 */     return !hasOtherAttendees();
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public ZAttendee getMatchingAttendee(Account acct, String identityId)
/*      */     throws ServiceException
/*      */   {
/*      */     Identity identity;
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/* 1392 */     if (identityId != null) {
/* 1393 */       Identity identity = acct.getIdentityById(identityId);
/* 1394 */       if (identity == null) {
/* 1395 */         ZimbraLog.calendar.warn("No such identity " + identityId + " for account " + acct.getName());
/* 1396 */         identity = acct.getDefaultIdentity();
/*      */       }
/*      */     } else {
/* 1399 */       identity = acct.getDefaultIdentity();
/*      */     }
/*      */     
/* 1402 */     String identityEmail = identity.getAttr("zimbraPrefFromAddress");
/* 1403 */     ZAttendee acctMatch = null;
/* 1404 */     List<ZAttendee> attendees = getAttendees();
/* 1405 */     AccountUtil.AccountAddressMatcher acctMatcher = new AccountUtil.AccountAddressMatcher(acct);
/* 1406 */     for (ZAttendee at : attendees) {
/* 1407 */       String thisAtEmail = at.getAddress();
/*      */       
/* 1409 */       if ((identityEmail != null) && (identityEmail.equalsIgnoreCase(thisAtEmail)))
/* 1410 */         return at;
/* 1411 */       if ((acctMatch == null) && (acctMatcher.matches(thisAtEmail))) {
/* 1412 */         acctMatch = at;
/*      */         
/* 1414 */         if (identityEmail == null)
/* 1415 */           return at;
/*      */       }
/*      */     }
/* 1418 */     return acctMatch;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public ZAttendee getMatchingAttendee(Account acct)
/*      */     throws ServiceException
/*      */   {
/* 1429 */     return getMatchingAttendee(acct, null);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public ZAttendee getMatchingAttendee(String atName)
/*      */     throws ServiceException
/*      */   {
/* 1441 */     List<ZAttendee> attendees = getAttendees();
/* 1442 */     for (ZAttendee at : attendees) {
/* 1443 */       String thisAtEmail = at.getAddress();
/* 1444 */       if ((thisAtEmail != null) && (thisAtEmail.equalsIgnoreCase(atName))) {
/* 1445 */         return at;
/*      */       }
/*      */     }
/* 1448 */     return null;
/*      */   }
/*      */   
/*      */   public ZAttendee getMatchingAttendee(ZAttendee matchAttendee)
/*      */     throws ServiceException
/*      */   {
/* 1454 */     AccountUtil.AccountAddressMatcher acctMatcher = null;
/* 1455 */     String matchAddress = matchAttendee.getAddress();
/* 1456 */     if (matchAddress != null) {
/* 1457 */       Account matchAcct = Provisioning.getInstance().get(Key.AccountBy.name, matchAddress);
/* 1458 */       if (matchAcct != null) {
/* 1459 */         acctMatcher = new AccountUtil.AccountAddressMatcher(matchAcct);
/*      */       }
/*      */     }
/* 1462 */     for (ZAttendee at : getAttendees()) {
/* 1463 */       if ((matchAttendee.addressesMatch(at)) || ((acctMatcher != null) && (acctMatcher.matches(at.getAddress())))) {
/* 1464 */         return at;
/*      */       }
/*      */     }
/* 1467 */     return null;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   private static final String OUTLOOK_GLOBAL_ID_PREFIX = "040000008200E00074C5B7101A82E008";
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public boolean updateMatchingAttendeesFromReply(Invite reply)
/*      */     throws ServiceException
/*      */   {
/* 1482 */     List<ZAttendee> attendees = getAttendees();
/*      */     
/* 1484 */     ArrayList<ZAttendee> toAdd = new ArrayList();
/*      */     
/* 1486 */     boolean modified = false;
/*      */     
/* 1488 */     for (ZAttendee replyAt : reply.getAttendees()) {
/* 1489 */       ZAttendee at = getMatchingAttendee(replyAt);
/* 1490 */       if (at != null)
/*      */       {
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/* 1507 */         if ((replyAt.hasPartStat()) && (!replyAt.getPartStat().equals(at.getPartStat()))) {
/* 1508 */           at.setPartStat(replyAt.getPartStat());
/* 1509 */           modified = true;
/*      */         }
/*      */       }
/*      */       else {
/* 1513 */         toAdd.add(replyAt);
/*      */       }
/*      */     }
/* 1516 */     if (toAdd.size() > 0) {
/* 1517 */       for (ZAttendee add : toAdd) {
/* 1518 */         modified = true;
/* 1519 */         attendees.add(add);
/*      */       }
/*      */     }
/* 1522 */     return modified;
/*      */   }
/*      */   
/*      */   public List<ZAttendee> getAttendees() {
/* 1526 */     return this.mAttendees;
/*      */   }
/*      */   
/*      */   public void clearAttendees() {
/* 1530 */     this.mAttendees.clear();
/*      */   }
/*      */   
/*      */   public void addAttendee(ZAttendee at) {
/* 1534 */     this.mAttendees.add(at);
/*      */   }
/*      */   
/*      */   public void setOrganizer(ZOrganizer org) {
/* 1538 */     this.mOrganizer = org;
/*      */   }
/*      */   
/*      */ 
/*      */   public ZOrganizer getOrganizer()
/*      */   {
/* 1544 */     return this.mOrganizer;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public Account getOrganizerAccount()
/*      */     throws ServiceException
/*      */   {
/* 1554 */     Account account = null;
/* 1555 */     if ((this.mIsOrganizer) && (this.mCalItem != null))
/* 1556 */       return this.mCalItem.getAccount();
/* 1557 */     if (hasOrganizer()) {
/* 1558 */       String address = getOrganizer().getAddress();
/* 1559 */       if (address != null) {
/*      */         try {
/* 1561 */           account = Provisioning.getInstance().get(Key.AccountBy.name, address);
/*      */         } catch (ServiceException e) {
/* 1563 */           if ("service.INVALID_REQUEST".equals(e.getCode())) {
/* 1564 */             ZimbraLog.calendar.warn("Ignoring invalid organizer address: " + address);
/*      */           } else
/* 1566 */             throw e;
/*      */         }
/*      */       }
/* 1569 */     } else if (this.mCalItem != null) {
/* 1570 */       account = this.mCalItem.getAccount();
/*      */     }
/* 1572 */     return account;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public boolean isOrganizer()
/*      */   {
/* 1580 */     return this.mIsOrganizer;
/*      */   }
/*      */   
/* 1583 */   public void setIsOrganizer(Account acct) throws ServiceException { this.mIsOrganizer = thisAcctIsOrganizer(acct); }
/*      */   
/*      */   public void setIsOrganizer(boolean isOrganizer) {
/* 1586 */     this.mIsOrganizer = isOrganizer;
/*      */   }
/*      */   
/*      */   public boolean isLocalOnly()
/*      */   {
/* 1591 */     return (this.mLocalOnly) && (!this.mIsOrganizer);
/*      */   }
/*      */   
/*      */   public void setLocalOnly(boolean localOnly) {
/* 1595 */     this.mLocalOnly = localOnly;
/*      */   }
/*      */   
/*      */   public boolean isEvent() {
/* 1599 */     return this.type == MailItem.Type.APPOINTMENT;
/*      */   }
/*      */   
/*      */   public boolean isTodo() {
/* 1603 */     return this.type == MailItem.Type.TASK;
/*      */   }
/*      */   
/*      */   public MailItem.Type getItemType() {
/* 1607 */     return this.type;
/*      */   }
/*      */   
/*      */   public void setItemType(MailItem.Type type) {
/* 1611 */     this.type = type;
/*      */     
/*      */ 
/* 1614 */     if ((type == MailItem.Type.TASK) && ("CONF".equals(this.mStatus))) {
/* 1615 */       this.mStatus = "NEED";
/*      */     }
/*      */   }
/*      */   
/*      */   public TimeZoneMap getTimeZoneMap()
/*      */   {
/* 1621 */     return this.mTzMap;
/*      */   }
/*      */   
/* 1624 */   public ZCalendar.ZVCalendar newToICalendar(boolean includePrivateData) throws ServiceException { return newToICalendar(OUTLOOK_COMPAT_ALLDAY, includePrivateData); }
/*      */   
/*      */   public ZCalendar.ZVCalendar newToICalendar(boolean useOutlookCompatMode, boolean includePrivateData)
/*      */     throws ServiceException
/*      */   {
/* 1629 */     ZCalendar.ZVCalendar vcal = new ZCalendar.ZVCalendar();
/* 1630 */     vcal.addVersionAndProdId();
/*      */     
/* 1632 */     vcal.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.METHOD, this.mMethod.toString()));
/*      */     
/*      */     Iterator<ICalTimeZone> iter;
/* 1635 */     if ((!isAllDayEvent()) || (useOutlookCompatMode)) {
/* 1636 */       for (iter = this.mTzMap.tzIterator(); iter.hasNext();) {
/* 1637 */         ICalTimeZone cur = (ICalTimeZone)iter.next();
/* 1638 */         vcal.addComponent(cur.newToVTimeZone());
/*      */       }
/*      */     }
/*      */     
/* 1642 */     vcal.addComponent(newToVComponent(useOutlookCompatMode, includePrivateData));
/* 1643 */     return vcal;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public static List<Invite> createFromCalendar(Account account, String fragment, ZCalendar.ZVCalendar cal, boolean sentByMe)
/*      */     throws ServiceException
/*      */   {
/* 1652 */     return createFromCalendar(account, fragment, cal, sentByMe, null, 0);
/*      */   }
/*      */   
/*      */   public static List<Invite> createFromCalendar(Account account, String fragment, ZCalendar.ZVCalendar cal, boolean sentByMe, Mailbox mbx, int mailItemId)
/*      */     throws ServiceException
/*      */   {
/* 1658 */     List<Invite> list = new ArrayList();
/* 1659 */     createFromCalendar(list, account, fragment, cal, sentByMe, mbx, mailItemId, false, null);
/* 1660 */     return list;
/*      */   }
/*      */   
/*      */   public static List<Invite> createFromCalendar(Account account, String fragment, List<ZCalendar.ZVCalendar> cals, boolean sentByMe)
/*      */     throws ServiceException
/*      */   {
/* 1666 */     return createFromCalendar(account, fragment, cals, sentByMe, false, null);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public static void createFromCalendar(Account account, String fragment, String method, TimeZoneMap tzmap, Iterator<ZCalendar.ZComponent> compIter, boolean sentByMe, boolean continueOnError, InviteVisitor visitor)
/*      */     throws ServiceException
/*      */   {
/* 1674 */     createFromCalendar(null, account, fragment, method, tzmap, compIter, sentByMe, null, 0, continueOnError, visitor);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public static List<Invite> createFromCalendar(Account account, String fragment, List<ZCalendar.ZVCalendar> cals, boolean sentByMe, boolean continueOnError, InviteVisitor visitor)
/*      */     throws ServiceException
/*      */   {
/* 1682 */     List<Invite> list = new ArrayList();
/* 1683 */     for (ZCalendar.ZVCalendar cal : cals) {
/* 1684 */       createFromCalendar(list, account, fragment, cal, sentByMe, (Mailbox)null, 0, continueOnError, visitor);
/*      */     }
/*      */     
/* 1687 */     return list;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   private static void createFromCalendar(List<Invite> toAdd, Account account, String fragment, ZCalendar.ZVCalendar cal, boolean sentByMe, Mailbox mbx, int mailItemId, boolean continueOnError, InviteVisitor visitor)
/*      */     throws ServiceException
/*      */   {
/* 1695 */     String method = cal.getPropVal(ZCalendar.ICalTok.METHOD, ZCalendar.ICalTok.PUBLISH.toString());
/*      */     
/*      */ 
/* 1698 */     TimeZoneMap tzmap = new TimeZoneMap(Util.getAccountTimeZone(account));
/* 1699 */     List<ZCalendar.ZComponent> components = Lists.newArrayList(cal.getComponentIterator());
/* 1700 */     for (ZCalendar.ZComponent comp : components) {
/* 1701 */       if (ZCalendar.ICalTok.VTIMEZONE.equals(comp.getTok())) {
/* 1702 */         ICalTimeZone tz = ICalTimeZone.fromVTimeZone(comp);
/* 1703 */         tzmap.add(tz);
/*      */       }
/*      */     }
/*      */     
/* 1707 */     createFromCalendar(toAdd, account, fragment, method, tzmap, cal.getComponentIterator(), sentByMe, mbx, mailItemId, continueOnError, visitor);
/*      */   }
/*      */   
/*      */ 
/*      */   private static void createFromCalendar(List<Invite> toAdd, Account account, String fragment, String method, TimeZoneMap tzmap, Iterator<ZCalendar.ZComponent> compIter, boolean sentByMe, Mailbox mbx, int mailItemId, boolean continueOnError, InviteVisitor visitor)
/*      */     throws ServiceException
/*      */   {
/* 1714 */     int compNum = 0;
/* 1715 */     while (compIter.hasNext()) {
/* 1716 */       ZCalendar.ZComponent comp = (ZCalendar.ZComponent)compIter.next();
/* 1717 */       Invite newInv = null;
/*      */       try
/*      */       {
/* 1720 */         ZCalendar.ICalTok compTypeTok = comp.getTok();
/* 1721 */         if (compTypeTok != null) { MailItem.Type type;
/* 1722 */           MailItem.Type type; if (ZCalendar.ICalTok.VTODO.equals(compTypeTok)) {
/* 1723 */             type = MailItem.Type.TASK;
/*      */           } else {
/* 1725 */             type = MailItem.Type.APPOINTMENT;
/*      */           }
/* 1727 */           switch (compTypeTok) {
/*      */           case VEVENT: 
/*      */           case VTODO: 
/* 1730 */             boolean isEvent = ZCalendar.ICalTok.VEVENT.equals(compTypeTok);
/* 1731 */             boolean isTodo = ZCalendar.ICalTok.VTODO.equals(compTypeTok);
/*      */             try {
/* 1733 */               newInv = new Invite(type, method, tzmap, false);
/* 1734 */               newInv.setLocalOnly(false);
/* 1735 */               if (toAdd != null) {
/* 1736 */                 toAdd.add(newInv);
/*      */               }
/* 1738 */               List<Object> addRecurs = new ArrayList();
/* 1739 */               List<Object> subRecurs = new ArrayList();
/*      */               
/* 1741 */               newInv.setComponentNum(compNum);
/* 1742 */               if (mbx != null)
/* 1743 */                 newInv.setMailboxId(mbx.getId());
/* 1744 */               newInv.setMailItemId(mailItemId);
/* 1745 */               newInv.setSentByMe(sentByMe);
/* 1746 */               compNum++;
/*      */               
/* 1748 */               List<ZCalendar.ZComponent> subcomponents = Lists.newArrayList(comp.getComponentIterator());
/* 1749 */               for (ZCalendar.ZComponent subcomp : subcomponents) {
/* 1750 */                 ZCalendar.ICalTok subCompTypeTok = subcomp.getTok();
/* 1751 */                 switch (subCompTypeTok) {
/*      */                 case VALARM: 
/* 1753 */                   Alarm alarm = Alarm.parse(subcomp);
/* 1754 */                   if (alarm != null) {
/* 1755 */                     newInv.addAlarm(alarm);
/*      */                   }
/*      */                   break;
/*      */                 }
/*      */                 
/*      */               }
/* 1761 */               boolean isTodoCompleted = false;
/* 1762 */               boolean sawIntendedFreeBusy = false;
/* 1763 */               List<ZCalendar.ZProperty> properties = Lists.newArrayList(comp.getPropertyIterator());
/* 1764 */               for (ZCalendar.ZProperty prop : properties) {
/* 1765 */                 String propVal = prop.getValue();
/* 1766 */                 ZCalendar.ICalTok propToken = prop.getToken();
/* 1767 */                 if (propToken == null)
/*      */                 {
/*      */ 
/*      */ 
/* 1771 */                   if ((propVal != null) && (propVal.length() >= 1))
/*      */                   {
/* 1773 */                     String name = prop.getName();
/* 1774 */                     if ((name.startsWith("X-")) || (name.startsWith("x-")))
/* 1775 */                       newInv.addXProp(prop);
/* 1776 */                   } } else if (propToken.equals(ZCalendar.ICalTok.CATEGORIES)) {
/* 1777 */                   List<String> categories = prop.getValueList();
/* 1778 */                   if ((categories != null) && (!categories.isEmpty())) {
/* 1779 */                     for (String cat : categories) {
/* 1780 */                       newInv.addCategory(cat);
/*      */                     }
/*      */                     
/*      */                   }
/*      */                   
/*      */ 
/*      */                 }
/* 1787 */                 else if ((propVal != null) && (propVal.length() >= 1))
/*      */                 {
/* 1789 */                   switch (propToken) {
/*      */                   case ORGANIZER: 
/* 1791 */                     newInv.setOrganizer(new ZOrganizer(prop));
/* 1792 */                     break;
/*      */                   case ATTENDEE: 
/* 1794 */                     newInv.addAttendee(new ZAttendee(prop));
/* 1795 */                     break;
/*      */                   case DTSTAMP: 
/* 1797 */                     ParsedDateTime dtstamp = ParsedDateTime.parse(prop, tzmap);
/* 1798 */                     newInv.setDtStamp(dtstamp.getUtcTime());
/* 1799 */                     break;
/*      */                   case LAST_MODIFIED: 
/* 1801 */                     ParsedDateTime lastModified = ParsedDateTime.parse(prop, tzmap);
/* 1802 */                     newInv.setLastModified(lastModified.getUtcTime());
/* 1803 */                     break;
/*      */                   case RECURRENCE_ID: 
/* 1805 */                     ParsedDateTime rid = ParsedDateTime.parse(prop, tzmap);
/* 1806 */                     if (DebugConfig.enableThisAndFuture) {
/* 1807 */                       newInv.setRecurId(new RecurId(rid, prop.paramVal(ZCalendar.ICalTok.RANGE, null)));
/*      */                     } else {
/* 1809 */                       newInv.setRecurId(new RecurId(rid, RecurId.RANGE_NONE));
/*      */                     }
/* 1811 */                     break;
/*      */                   case SEQUENCE: 
/* 1813 */                     newInv.setSeqNo(prop.getIntValue());
/* 1814 */                     break;
/*      */                   case DTSTART: 
/* 1816 */                     ParsedDateTime dtstart = ParsedDateTime.parse(prop, tzmap);
/* 1817 */                     newInv.setDtStart(dtstart);
/* 1818 */                     if (!dtstart.hasTime())
/* 1819 */                       newInv.setIsAllDayEvent(true);
/*      */                     break;
/*      */                   case DTEND: 
/* 1822 */                     if (isEvent) {
/* 1823 */                       ParsedDateTime dtend = ParsedDateTime.parse(prop, tzmap);
/* 1824 */                       newInv.setDtEnd(dtend);
/* 1825 */                       if (!dtend.hasTime())
/* 1826 */                         newInv.setIsAllDayEvent(true); }
/* 1827 */                     break;
/*      */                   
/*      */                   case DUE: 
/* 1830 */                     if (isTodo) {
/* 1831 */                       ParsedDateTime due = ParsedDateTime.parse(prop, tzmap);
/*      */                       
/* 1833 */                       newInv.setDtEnd(due);
/* 1834 */                       if (!due.hasTime())
/* 1835 */                         newInv.setIsAllDayEvent(true); }
/* 1836 */                     break;
/*      */                   
/*      */                   case DURATION: 
/* 1839 */                     ParsedDuration dur = ParsedDuration.parse(propVal);
/* 1840 */                     newInv.setDuration(dur);
/* 1841 */                     break;
/*      */                   case LOCATION: 
/* 1843 */                     newInv.setLocation(propVal);
/* 1844 */                     break;
/*      */                   case SUMMARY: 
/* 1846 */                     String summary = propVal;
/* 1847 */                     if (summary != null)
/*      */                     {
/* 1849 */                       summary = summary.replaceAll("[\\\r\\\n]+", " ");
/*      */                     }
/* 1851 */                     prop.setValue(summary);
/* 1852 */                     newInv.setName(summary);
/* 1853 */                     break;
/*      */                   case DESCRIPTION: 
/* 1855 */                     newInv.setDescription(propVal, newInv.mDescHtml);
/* 1856 */                     newInv.setFragment(Fragment.getFragment(propVal, true));
/* 1857 */                     break;
/*      */                   case X_ALT_DESC: 
/* 1859 */                     ZCalendar.ZParameter fmttype = prop.getParameter(ZCalendar.ICalTok.FMTTYPE);
/* 1860 */                     if ((fmttype != null) && ("text/html".equalsIgnoreCase(fmttype.getValue()))) {
/* 1861 */                       String html = propVal;
/* 1862 */                       newInv.setDescription(newInv.mDescription, html);
/*      */                     }
/*      */                     else {
/* 1865 */                       newInv.addXProp(prop);
/*      */                     }
/* 1867 */                     break;
/*      */                   case COMMENT: 
/* 1869 */                     newInv.addComment(propVal);
/* 1870 */                     break;
/*      */                   case UID: 
/* 1872 */                     newInv.setUid(propVal);
/* 1873 */                     break;
/*      */                   case RRULE: 
/* 1875 */                     ZRecur recur = new ZRecur(propVal, tzmap);
/* 1876 */                     addRecurs.add(recur);
/* 1877 */                     newInv.setIsRecurrence(true);
/* 1878 */                     break;
/*      */                   case RDATE: 
/* 1880 */                     if (DebugConfig.enableRdate) {
/* 1881 */                       RdateExdate rdate = RdateExdate.parse(prop, tzmap);
/* 1882 */                       addRecurs.add(rdate);
/* 1883 */                       newInv.setIsRecurrence(true); }
/* 1884 */                     break;
/*      */                   
/*      */                   case EXRULE: 
/* 1887 */                     ZRecur exrecur = new ZRecur(propVal, tzmap);
/* 1888 */                     subRecurs.add(exrecur);
/* 1889 */                     newInv.setIsRecurrence(true);
/* 1890 */                     break;
/*      */                   case EXDATE: 
/* 1892 */                     RdateExdate exdate = RdateExdate.parse(prop, tzmap);
/* 1893 */                     subRecurs.add(exdate);
/* 1894 */                     newInv.setIsRecurrence(true);
/* 1895 */                     break;
/*      */                   case STATUS: 
/* 1897 */                     String status = IcalXmlStrMap.sStatusMap.toXml(propVal);
/* 1898 */                     if (status != null) {
/* 1899 */                       if ("INPR".equals(status)) {
/* 1900 */                         String zstatus = prop.getParameterVal(ZCalendar.ICalTok.X_ZIMBRA_STATUS, null);
/* 1901 */                         if ((ZCalendar.ICalTok.X_ZIMBRA_STATUS_WAITING.toString().equals(zstatus)) || (ZCalendar.ICalTok.X_ZIMBRA_STATUS_DEFERRED.toString().equals(zstatus)))
/*      */                         {
/* 1903 */                           newInv.setStatus(IcalXmlStrMap.sStatusMap.toXml(zstatus));
/*      */                         } else {
/* 1905 */                           newInv.setStatus(status);
/*      */                         }
/*      */                       } else {
/* 1908 */                         newInv.setStatus(status);
/* 1909 */                         if ((isTodo) && ("COMP".equals(status))) {
/* 1910 */                           isTodoCompleted = true;
/*      */                         }
/*      */                       }
/*      */                     }
/*      */                     break;
/*      */                   case TRANSP: 
/* 1916 */                     if ((isEvent) && (!sawIntendedFreeBusy)) {
/* 1917 */                       String transp = IcalXmlStrMap.sTranspMap.toXml(propVal);
/* 1918 */                       if (transp != null) {
/* 1919 */                         newInv.setTransparency(transp);
/*      */                         
/*      */ 
/* 1922 */                         if (newInv.isTransparent())
/* 1923 */                           newInv.setFreeBusy("F");
/*      */                       } }
/* 1925 */                     break;
/*      */                   
/*      */                   case CLASS: 
/* 1928 */                     String classProp = IcalXmlStrMap.sClassMap.toXml(propVal);
/* 1929 */                     if (classProp != null)
/* 1930 */                       newInv.setClassProp(classProp);
/*      */                     break;
/*      */                   case X_MICROSOFT_CDO_ALLDAYEVENT: 
/* 1933 */                     if ((isEvent) && 
/* 1934 */                       (prop.getBoolValue())) {
/* 1935 */                       newInv.setIsAllDayEvent(true);
/*      */                     }
/*      */                     break;
/*      */                   case X_MICROSOFT_CDO_INTENDEDSTATUS: 
/* 1939 */                     sawIntendedFreeBusy = true;
/* 1940 */                     if (isEvent) {
/* 1941 */                       String fb = IcalXmlStrMap.sOutlookFreeBusyMap.toXml(propVal);
/* 1942 */                       if (fb != null) {
/* 1943 */                         newInv.setFreeBusy(fb);
/*      */                         
/* 1945 */                         if ("F".equals(fb)) {
/* 1946 */                           newInv.setTransparency("T");
/*      */                         } else
/* 1948 */                           newInv.setTransparency("O");
/*      */                       } }
/* 1950 */                     break;
/*      */                   
/*      */                   case PRIORITY: 
/* 1953 */                     String prio = propVal;
/* 1954 */                     if (prio != null)
/* 1955 */                       newInv.setPriority(prio);
/*      */                     break;
/*      */                   case PERCENT_COMPLETE: 
/* 1958 */                     if (isTodo) {
/* 1959 */                       String pctComplete = propVal;
/* 1960 */                       if (pctComplete != null) {
/* 1961 */                         newInv.setPercentComplete(pctComplete);
/* 1962 */                         if (prop.getIntValue() == 100)
/* 1963 */                           isTodoCompleted = true;
/*      */                       } }
/* 1965 */                     break;
/*      */                   
/*      */                   case COMPLETED: 
/* 1968 */                     if (isTodo) {
/* 1969 */                       ParsedDateTime completed = ParsedDateTime.parseUtcOnly(propVal);
/* 1970 */                       newInv.setCompleted(completed.getUtcTime());
/* 1971 */                       isTodoCompleted = true; }
/* 1972 */                     break;
/*      */                   
/*      */                   case CONTACT: 
/* 1975 */                     newInv.addContact(propVal);
/* 1976 */                     break;
/*      */                   case GEO: 
/* 1978 */                     Geo geo = Geo.parse(prop);
/* 1979 */                     newInv.setGeo(geo);
/* 1980 */                     break;
/*      */                   case URL: 
/* 1982 */                     newInv.setUrl(propVal);
/* 1983 */                     break;
/*      */                   case X_ZIMBRA_LOCAL_ONLY: 
/* 1985 */                     if (prop.getBoolValue())
/* 1986 */                       newInv.setLocalOnly(true);
/*      */                     break;
/*      */                   case X_ZIMBRA_DISCARD_EXCEPTIONS: 
/* 1989 */                     newInv.addXProp(prop);
/* 1990 */                     break;
/*      */                   case X_ZIMBRA_CHANGES: 
/* 1992 */                     newInv.addXProp(prop);
/* 1993 */                     break;
/*      */                   case ATTACH: 
/* 1995 */                     Attach attach = Attach.parse(prop);
/* 1996 */                     if (attach.getBinaryB64Data() != null) {
/* 1997 */                       newInv.addIcalendarAttach(attach);
/*      */                     }
/*      */                     break;
/*      */                   }
/*      */                   
/*      */                 }
/*      */               }
/* 2004 */               if (isTodoCompleted)
/*      */               {
/* 2006 */                 newInv.setStatus("COMP");
/*      */                 
/* 2008 */                 newInv.setPercentComplete(Integer.toString(100));
/* 2009 */                 if (newInv.getCompleted() == 0L) {
/* 2010 */                   newInv.setCompleted(System.currentTimeMillis());
/*      */                 }
/*      */               }
/* 2013 */               newInv.setIsOrganizer(account);
/*      */               
/* 2015 */               newInv.validateDuration();
/*      */               
/* 2017 */               ParsedDuration duration = newInv.getDuration();
/* 2018 */               boolean durationCalculated = false;
/* 2019 */               if (duration == null) {
/* 2020 */                 ParsedDateTime end = newInv.getEndTime();
/* 2021 */                 if ((end != null) && (newInv.getStartTime() != null)) {
/* 2022 */                   duration = end.difference(newInv.getStartTime());
/* 2023 */                   durationCalculated = true;
/*      */                 }
/*      */               }
/*      */               
/* 2027 */               if ((!addRecurs.isEmpty()) || (!subRecurs.isEmpty()))
/*      */               {
/* 2029 */                 ParsedDateTime st = newInv.getStartTime();
/* 2030 */                 if (st == null) {
/* 2031 */                   ParsedDateTime et = newInv.getEndTime();
/* 2032 */                   if (et != null) {
/* 2033 */                     if (et.hasTime()) {
/* 2034 */                       st = et.add(ParsedDuration.NEGATIVE_ONE_SECOND);
/*      */                     } else
/* 2036 */                       st = et.add(ParsedDuration.NEGATIVE_ONE_DAY);
/* 2037 */                     newInv.setDtStart(st);
/*      */                   }
/*      */                   else {
/* 2040 */                     throw ServiceException.INVALID_REQUEST("recurrence used without DTSTART", null);
/*      */                   }
/*      */                 }
/* 2043 */                 if ((durationCalculated) && (newInv.getItemType() == MailItem.Type.TASK)) {
/* 2044 */                   if ((newInv.getStartTime() != null) && (!newInv.getStartTime().hasTime())) {
/* 2045 */                     duration = ParsedDuration.ONE_DAY;
/*      */                   } else {
/* 2047 */                     duration = ParsedDuration.ONE_SECOND;
/*      */                   }
/*      */                 }
/*      */               }
/*      */               
/* 2052 */               InviteInfo inviteInfo = new InviteInfo(newInv);
/* 2053 */               List<Recurrence.IRecurrence> addRules = new ArrayList();
/* 2054 */               Iterator<Object> iter; if (addRecurs.size() > 0) {
/* 2055 */                 for (iter = addRecurs.iterator(); iter.hasNext();) {
/* 2056 */                   Object next = iter.next();
/* 2057 */                   if ((next instanceof ZRecur)) {
/* 2058 */                     ZRecur cur = (ZRecur)next;
/* 2059 */                     addRules.add(new Recurrence.SimpleRepeatingRule(newInv.getStartTime(), duration, cur, inviteInfo));
/* 2060 */                   } else if ((next instanceof RdateExdate)) {
/* 2061 */                     RdateExdate rdate = (RdateExdate)next;
/* 2062 */                     addRules.add(new Recurrence.SingleDates(rdate, duration, inviteInfo));
/*      */                   }
/*      */                 }
/*      */               }
/* 2066 */               List<Recurrence.IRecurrence> subRules = new ArrayList();
/* 2067 */               Iterator<Object> iter; if (subRecurs.size() > 0) {
/* 2068 */                 for (iter = subRecurs.iterator(); iter.hasNext();) {
/* 2069 */                   Object next = iter.next();
/* 2070 */                   if ((next instanceof ZRecur)) {
/* 2071 */                     ZRecur cur = (ZRecur)iter.next();
/* 2072 */                     subRules.add(new Recurrence.SimpleRepeatingRule(newInv.getStartTime(), duration, cur, inviteInfo));
/* 2073 */                   } else if ((next instanceof RdateExdate)) {
/* 2074 */                     RdateExdate exdate = (RdateExdate)next;
/* 2075 */                     subRules.add(new Recurrence.SingleDates(exdate, duration, inviteInfo));
/*      */                   }
/*      */                 }
/*      */               }
/*      */               
/* 2080 */               if (newInv.hasRecurId()) {
/* 2081 */                 if (addRules.size() > 0) {
/* 2082 */                   newInv.setRecurrence(new Recurrence.ExceptionRule(newInv.getRecurId(), newInv.getStartTime(), duration, new InviteInfo(newInv), addRules, subRules));
/*      */                 }
/*      */                 
/*      */               }
/* 2086 */               else if (addRules.size() > 0) {
/* 2087 */                 newInv.setRecurrence(new Recurrence.RecurrenceRule(newInv.getStartTime(), duration, new InviteInfo(newInv), addRules, subRules));
/*      */               }
/*      */               
/*      */ 
/* 2091 */               String location = newInv.getLocation();
/* 2092 */               if (location == null) {
/* 2093 */                 newInv.setLocation("");
/*      */               }
/*      */               
/* 2096 */               if (visitor != null)
/* 2097 */                 visitor.visit(newInv);
/*      */             } catch (java.text.ParseException e) {
/* 2099 */               throw ServiceException.PARSE_ERROR("Unable to parse iCalendar data: " + e.getMessage(), e);
/*      */             }
/*      */           }
/*      */           
/*      */         }
/*      */       }
/*      */       catch (ServiceException e)
/*      */       {
/* 2107 */         if (!continueOnError) throw e;
/* 2108 */         if (newInv != null) {
/* 2109 */           logIcsParseImportError(newInv, e);
/*      */         } else
/* 2111 */           ZimbraLog.calendar.warn("Skipping error during ics parse/import", e);
/*      */       } catch (RuntimeException e) {
/* 2113 */         if (!continueOnError) throw e;
/* 2114 */         if (newInv != null) {
/* 2115 */           logIcsParseImportError(newInv, e);
/*      */         } else
/* 2117 */           ZimbraLog.calendar.warn("Skipping error during ics parse/import", e);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   public static void logIcsParseImportError(Invite inv, Exception e) {
/* 2123 */     String uid = inv.getUid();
/* 2124 */     String recurrenceId = inv.hasRecurId() ? inv.getRecurId().toString() : null;
/* 2125 */     int seq = inv.getSeqNo();
/* 2126 */     String dtStart = inv.getStartTime() != null ? inv.getStartTime().toString() : null;
/* 2127 */     String summary = inv.getName();
/* 2128 */     ZimbraLog.calendar.warn("Skipping error during ics parse/import: UID:" + uid + (recurrenceId != null ? ", RECURRENCE-ID:" + recurrenceId : "") + ", SEQUENCE:" + seq + (dtStart != null ? ", DTSTART:" + dtStart : "") + (summary != null ? ", SUMMARY:" + summary : ""), e);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   protected ZCalendar.ZComponent addInlineATTACHes(ZCalendar.ZComponent comp)
/*      */   {
/* 2138 */     MimeMessage mimeMsg = null;
/*      */     try {
/* 2140 */       mimeMsg = getMimeMessage();
/*      */     } catch (ServiceException e1) {
/* 2142 */       return comp;
/*      */     }
/* 2144 */     if (mimeMsg == null) {
/* 2145 */       return comp;
/*      */     }
/*      */     try {
/* 2148 */       List<MPartInfo> parts = Mime.getParts(mimeMsg, "utf-8");
/* 2149 */       if ((parts != null) && (!parts.isEmpty()))
/* 2150 */         for (MPartInfo body : ((MPartInfo)parts.get(0)).getChildren())
/* 2151 */           if (!body.isMultipart())
/*      */           {
/*      */ 
/* 2154 */             MimePart mp = body.getMimePart();
/* 2155 */             String ctype = StringUtil.stripControlCharacters(body.getContentType());
/* 2156 */             if ("text/calendar".equalsIgnoreCase(ctype))
/*      */             {
/*      */               try
/*      */               {
/* 2160 */                 ContentType ct = new ContentType(body.getMimePart().getContentType());
/* 2161 */                 if (ct.getParameter("method") != null) {
/*      */                   continue;
/*      */                 }
/*      */               }
/*      */               catch (MessagingException e) {}
/*      */             } else {
/* 2167 */               String contentType = StringUtil.stripControlCharacters(body.getContentType());
/* 2168 */               String fileName = Mime.getFilename(mp);
/* 2169 */               InputStream in = mp.getInputStream();Throwable localThrowable2 = null;
/* 2170 */               try { byte[] rawBytes = IOUtils.toByteArray(in);
/* 2171 */                 Attach attachment = Attach.fromUnencodedAndContentType(rawBytes, contentType);
/* 2172 */                 if (!Strings.isNullOrEmpty(fileName)) {
/* 2173 */                   attachment.setFileName(fileName);
/*      */                 }
/* 2175 */                 comp.addProperty(attachment.toZProperty());
/*      */               }
/*      */               catch (Throwable localThrowable1)
/*      */               {
/* 2169 */                 localThrowable2 = localThrowable1;throw localThrowable1;
/*      */ 
/*      */ 
/*      */               }
/*      */               finally
/*      */               {
/*      */ 
/* 2176 */                 if (in != null) if (localThrowable2 != null) try { in.close(); } catch (Throwable x2) { localThrowable2.addSuppressed(x2); } else in.close();
/*      */               }
/*      */             }
/*      */           }
/* 2180 */     } catch (MessagingException|IOException e) { ZimbraLog.calendar.warn("Problem adding inline ATTACHes", e);
/*      */     }
/* 2182 */     return comp;
/*      */   }
/*      */   
/*      */   public ZCalendar.ZComponent newToVComponent(boolean useOutlookCompatAllDayEvents, boolean includePrivateData) throws ServiceException
/*      */   {
/* 2187 */     return newToVComponent(useOutlookCompatAllDayEvents, includePrivateData, false);
/*      */   }
/*      */   
/*      */   public ZCalendar.ZComponent newToVComponent(boolean useOutlookCompatAllDayEvents, boolean includePrivateData, boolean includeAttaches)
/*      */     throws ServiceException
/*      */   {
/* 2193 */     boolean isRequestPublishCancel = (ZCalendar.ICalTok.REQUEST.equals(this.mMethod)) || (ZCalendar.ICalTok.PUBLISH.equals(this.mMethod)) || (ZCalendar.ICalTok.CANCEL.equals(this.mMethod));
/*      */     
/*      */     ZCalendar.ICalTok compTok;
/* 2196 */     if (this.type == MailItem.Type.TASK) {
/* 2197 */       ZCalendar.ICalTok compTok = ZCalendar.ICalTok.VTODO;
/* 2198 */       useOutlookCompatAllDayEvents = false;
/*      */     } else {
/* 2200 */       compTok = ZCalendar.ICalTok.VEVENT;
/*      */     }
/* 2202 */     ZCalendar.ZComponent component = new ZCalendar.ZComponent(compTok);
/*      */     
/* 2204 */     component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.UID, getUid()));
/*      */     
/* 2206 */     Recurrence.IRecurrence recur = getRecurrence();
/* 2207 */     Iterator iter; if (recur != null) {
/* 2208 */       for (Iterator iter = recur.addRulesIterator(); (iter != null) && (iter.hasNext());) {
/* 2209 */         Recurrence.IRecurrence cur = (Recurrence.IRecurrence)iter.next();
/*      */         
/* 2211 */         switch (cur.getType()) {
/*      */         case 6: 
/* 2213 */           if (DebugConfig.enableRdate) {
/* 2214 */             Recurrence.SingleDates sd = (Recurrence.SingleDates)cur;
/* 2215 */             RdateExdate rdate = sd.getRdateExdate();
/* 2216 */             rdate.addAsSeparateProperties(component); }
/* 2217 */           break;
/*      */         
/*      */         case 5: 
/* 2220 */           Recurrence.SimpleRepeatingRule srr = (Recurrence.SimpleRepeatingRule)cur;
/* 2221 */           component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.RRULE, srr.getRule().toString()));
/*      */         }
/*      */         
/*      */       }
/*      */       
/* 2226 */       for (iter = recur.subRulesIterator(); (iter != null) && (iter.hasNext());) {
/* 2227 */         Recurrence.IRecurrence cur = (Recurrence.IRecurrence)iter.next();
/*      */         
/* 2229 */         switch (cur.getType()) {
/*      */         case 6: 
/* 2231 */           Recurrence.SingleDates sd = (Recurrence.SingleDates)cur;
/* 2232 */           RdateExdate exdate = sd.getRdateExdate();
/* 2233 */           exdate.addAsSeparateProperties(component);
/* 2234 */           break;
/*      */         case 5: 
/* 2236 */           Recurrence.SimpleRepeatingRule srr = (Recurrence.SimpleRepeatingRule)cur;
/* 2237 */           component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.EXRULE, srr.getRule().toString()));
/*      */         }
/*      */         
/*      */       }
/*      */     }
/*      */     
/* 2243 */     if ((includePrivateData) || (isPublic()))
/*      */     {
/* 2245 */       String name = getName();
/* 2246 */       if ((name != null) && (name.length() > 0)) {
/* 2247 */         component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.SUMMARY, name));
/*      */       }
/*      */       
/* 2250 */       String desc = getDescription();
/* 2251 */       if (desc != null)
/*      */       {
/* 2253 */         int delim = desc.indexOf("*~*~*~*~*~*~*~*~*~*");
/* 2254 */         if (delim >= 0) {
/* 2255 */           desc = desc.substring(delim + "*~*~*~*~*~*~*~*~*~*".length());
/* 2256 */           desc = desc.replaceFirst("^\\r?\\n\\r?\\n", "");
/*      */         }
/* 2258 */         if (desc.length() > 0)
/* 2259 */           component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.DESCRIPTION, desc));
/*      */       }
/* 2261 */       String descHtml = getDescriptionHtml();
/* 2262 */       if ((descHtml != null) && (descHtml.length() > 0)) {
/* 2263 */         ZCalendar.ZProperty altDesc = new ZCalendar.ZProperty(ZCalendar.ICalTok.X_ALT_DESC, descHtml);
/* 2264 */         altDesc.addParameter(new ZCalendar.ZParameter(ZCalendar.ICalTok.FMTTYPE, "text/html"));
/* 2265 */         component.addProperty(altDesc);
/*      */       }
/*      */       
/*      */ 
/* 2269 */       List<String> comments = getComments();
/* 2270 */       if ((comments != null) && (!comments.isEmpty())) {
/* 2271 */         for (String comment : comments) {
/* 2272 */           component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.COMMENT, comment));
/*      */         }
/*      */       }
/*      */       
/*      */ 
/* 2277 */       String location = getLocation();
/* 2278 */       if ((location != null) && (location.length() > 0)) {
/* 2279 */         component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.LOCATION, location.toString()));
/*      */       }
/*      */       
/* 2282 */       for (ZAttendee at : getAttendees()) {
/* 2283 */         component.addProperty(at.toProperty());
/*      */       }
/*      */       
/*      */ 
/* 2287 */       if (this.mPriority != null) {
/* 2288 */         component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.PRIORITY, this.mPriority));
/*      */       }
/*      */       
/* 2291 */       if ((isTodo()) && (this.mPercentComplete != null)) {
/* 2292 */         component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.PERCENT_COMPLETE, this.mPercentComplete));
/*      */       }
/*      */       
/* 2295 */       if ((isTodo()) && (this.mCompleted != 0L)) {
/* 2296 */         ParsedDateTime completed = ParsedDateTime.fromUTCTime(this.mCompleted);
/* 2297 */         component.addProperty(completed.toProperty(ZCalendar.ICalTok.COMPLETED, false));
/*      */       }
/*      */       
/*      */ 
/* 2301 */       List<String> categories = getCategories();
/* 2302 */       if ((categories != null) && (!categories.isEmpty())) {
/* 2303 */         ZCalendar.ZProperty catsProp = new ZCalendar.ZProperty(ZCalendar.ICalTok.CATEGORIES);
/* 2304 */         catsProp.setValueList(categories);
/* 2305 */         component.addProperty(catsProp);
/*      */       }
/*      */       
/*      */ 
/* 2309 */       List<String> contacts = getContacts();
/* 2310 */       if ((contacts != null) && (!contacts.isEmpty())) {
/* 2311 */         for (String contact : contacts) {
/* 2312 */           component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.CONTACT, contact));
/*      */         }
/*      */       }
/*      */       
/*      */ 
/* 2317 */       if (this.mGeo != null) {
/* 2318 */         component.addProperty(this.mGeo.toZProperty());
/*      */       }
/*      */       
/* 2321 */       for (Alarm alarm : this.mAlarms) {
/* 2322 */         ZCalendar.ZComponent alarmComp = alarm.toZComponent();
/* 2323 */         component.addComponent(alarmComp);
/*      */       }
/*      */       
/*      */ 
/* 2327 */       for (ZCalendar.ZProperty xprop : this.mXProps) {
/* 2328 */         component.addProperty(xprop);
/*      */       }
/*      */       
/*      */ 
/* 2332 */       if (hasOrganizer()) {
/* 2333 */         ZOrganizer organizer = getOrganizer();
/* 2334 */         ZCalendar.ZProperty orgProp = organizer.toProperty();
/* 2335 */         component.addProperty(orgProp);
/*      */         
/* 2337 */         if ((organizer.hasSentBy()) && (!ZCalendar.ICalTok.REPLY.equals(this.mMethod)) && (!ZCalendar.ICalTok.COUNTER.equals(this.mMethod))) {
/* 2338 */           String sentByParam = orgProp.paramVal(ZCalendar.ICalTok.SENT_BY, null);
/* 2339 */           if (sentByParam != null) {
/* 2340 */             ZCalendar.ZProperty xMsOlkSender = new ZCalendar.ZProperty("X-MS-OLK-SENDER");
/* 2341 */             xMsOlkSender.setValue(sentByParam);
/* 2342 */             component.addProperty(xMsOlkSender);
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*      */ 
/* 2349 */     ParsedDateTime dtstart = getStartTime();
/* 2350 */     if (dtstart != null) {
/* 2351 */       component.addProperty(dtstart.toProperty(ZCalendar.ICalTok.DTSTART, useOutlookCompatAllDayEvents));
/*      */     }
/*      */     
/* 2354 */     ParsedDateTime dtend = getEndTime();
/* 2355 */     if (dtend != null) {
/* 2356 */       ZCalendar.ICalTok prop = ZCalendar.ICalTok.DTEND;
/* 2357 */       if (isTodo())
/* 2358 */         prop = ZCalendar.ICalTok.DUE;
/* 2359 */       component.addProperty(dtend.toProperty(prop, useOutlookCompatAllDayEvents));
/*      */     }
/*      */     
/*      */ 
/* 2363 */     ParsedDuration dur = getDuration();
/* 2364 */     if (dur != null) {
/* 2365 */       component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.DURATION, dur.toString()));
/*      */     }
/*      */     
/* 2368 */     String status = getStatus();
/* 2369 */     String statusIcal = IcalXmlStrMap.sStatusMap.toIcal(status);
/* 2370 */     if (("WAITING".equals(status)) || ("DEFERRED".equals(status)))
/*      */     {
/* 2372 */       ZCalendar.ZParameter param = new ZCalendar.ZParameter(ZCalendar.ICalTok.X_ZIMBRA_STATUS, statusIcal);
/* 2373 */       ZCalendar.ZProperty prop = new ZCalendar.ZProperty(ZCalendar.ICalTok.STATUS, ZCalendar.ICalTok.IN_PROCESS.toString());
/* 2374 */       prop.addParameter(param);
/* 2375 */       component.addProperty(prop);
/*      */     } else {
/* 2377 */       component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.STATUS, statusIcal));
/*      */     }
/*      */     
/*      */ 
/* 2381 */     component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.CLASS, IcalXmlStrMap.sClassMap.toIcal(getClassProp())));
/*      */     
/* 2383 */     if (isEvent())
/*      */     {
/* 2385 */       if (isAllDayEvent()) {
/* 2386 */         component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.X_MICROSOFT_CDO_ALLDAYEVENT, true));
/*      */       }
/*      */       
/* 2389 */       if (isRequestPublishCancel) {
/* 2390 */         String outlookFreeBusy = IcalXmlStrMap.sOutlookFreeBusyMap.toIcal(getFreeBusy());
/* 2391 */         component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.X_MICROSOFT_CDO_INTENDEDSTATUS, outlookFreeBusy));
/*      */       }
/*      */       
/*      */ 
/* 2395 */       component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.TRANSP, IcalXmlStrMap.sTranspMap.toIcal(getTransparency())));
/*      */     }
/*      */     
/*      */ 
/*      */ 
/* 2400 */     RecurId recurId = getRecurId();
/* 2401 */     if (recurId != null) {
/* 2402 */       component.addProperty(recurId.toProperty(useOutlookCompatAllDayEvents));
/*      */     }
/*      */     
/* 2405 */     long lastModified = getLastModified();
/* 2406 */     if (lastModified != 0L) {
/* 2407 */       ParsedDateTime dtLastModified = ParsedDateTime.fromUTCTime(lastModified);
/* 2408 */       component.addProperty(dtLastModified.toProperty(ZCalendar.ICalTok.LAST_MODIFIED, false));
/*      */     }
/*      */     
/*      */ 
/* 2412 */     ParsedDateTime dtStamp = ParsedDateTime.fromUTCTime(getDTStamp());
/* 2413 */     component.addProperty(dtStamp.toProperty(ZCalendar.ICalTok.DTSTAMP, false));
/*      */     
/*      */ 
/* 2416 */     component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.SEQUENCE, getSeqNo()));
/*      */     
/*      */ 
/* 2419 */     String url = getUrl();
/* 2420 */     if ((url != null) && (url.length() > 0)) {
/* 2421 */       component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.URL, url));
/*      */     }
/* 2423 */     if (isLocalOnly()) {
/* 2424 */       component.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.X_ZIMBRA_LOCAL_ONLY, true));
/*      */     }
/* 2426 */     if (includeAttaches) {
/* 2427 */       addInlineATTACHes(component);
/*      */     }
/* 2429 */     return component;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public static Invite matchingInvite(Iterable<Invite> invites, RecurId aRecurId)
/*      */   {
/* 2437 */     if (invites == null) {
/* 2438 */       return null;
/*      */     }
/* 2440 */     for (Invite cur : invites)
/*      */     {
/* 2442 */       if (((cur.getRecurId() != null) && (cur.getRecurId().equals(aRecurId))) || ((cur.getRecurId() == null) && (aRecurId == null)))
/*      */       {
/* 2444 */         return cur;
/*      */       }
/*      */     }
/* 2447 */     return null;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public static Invite matchingInvite(Invite[] invites, RecurId aRecurId)
/*      */   {
/* 2455 */     return matchingInvite(Arrays.asList(invites), aRecurId);
/*      */   }
/*      */   
/*      */   public List<CalendarItem.Instance> getExdates() {
/* 2459 */     List<CalendarItem.Instance> exdates = Lists.newArrayList();
/* 2460 */     Recurrence.IRecurrence recurrence = getRecurrence();
/* 2461 */     if (recurrence == null) {
/* 2462 */       return exdates;
/*      */     }
/*      */     
/* 2465 */     for (Iterator<?> iter = recurrence.subRulesIterator(); (iter != null) && (iter.hasNext());) {
/* 2466 */       Recurrence.IRecurrence cur = (Recurrence.IRecurrence)iter.next();
/* 2467 */       switch (cur.getType()) {
/*      */       case 6: 
/* 2469 */         Recurrence.SingleDates sd = (Recurrence.SingleDates)cur;
/* 2470 */         RdateExdate exdate = sd.getRdateExdate();
/* 2471 */         if (exdate.isEXDATE()) {
/* 2472 */           exdates.addAll(sd.expandInstances(getMailItemId()));
/*      */         } else {
/* 2474 */           ZimbraLog.calendar.debug("RDATE '%s' ignored", new Object[] { exdate });
/*      */         }
/* 2476 */         break;
/*      */       
/*      */ 
/*      */       case 5: 
/* 2480 */         ZimbraLog.calendar.debug("EXRULE ignored - no longer supported in rfc5545");
/*      */       }
/*      */       
/*      */     }
/* 2484 */     return exdates;
/*      */   }
/*      */   
/*      */   public static List<CalendarItem.Instance> getExdates(Invite inv) {
/* 2488 */     List<CalendarItem.Instance> exdates = Lists.newArrayList();
/* 2489 */     if (inv == null) {
/* 2490 */       return exdates;
/*      */     }
/* 2492 */     return inv.getExdates();
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public static ZCalendar.ZComponent[] toVComponents(Invite[] invites, boolean includePrivateData, boolean useOutlookCompatAllDayEvents, boolean convertCanceledInstancesToExdates)
/*      */     throws ServiceException
/*      */   {
/* 2500 */     return toVComponents(invites, includePrivateData, useOutlookCompatAllDayEvents, convertCanceledInstancesToExdates, false);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static ZCalendar.ZComponent[] toVComponents(Invite[] invites, boolean includePrivateData, boolean useOutlookCompatAllDayEvents, boolean convertCanceledInstancesToExdates, boolean includeAttaches)
/*      */     throws ServiceException
/*      */   {
/* 2510 */     List<ZCalendar.ZComponent> comps = new ArrayList(invites.length);
/* 2511 */     if ((!convertCanceledInstancesToExdates) || (invites.length <= 1)) {
/* 2512 */       for (Invite inv : invites) {
/* 2513 */         ZCalendar.ZComponent comp = inv.newToVComponent(useOutlookCompatAllDayEvents, includePrivateData, includeAttaches);
/*      */         
/* 2515 */         comps.add(comp);
/*      */       }
/*      */     }
/*      */     else
/*      */     {
/* 2520 */       Invite seriesInv = null;
/* 2521 */       ZCalendar.ZComponent seriesComp = null;
/*      */       
/* 2523 */       for (Invite inv : invites) {
/* 2524 */         if (inv.isRecurrence()) {
/* 2525 */           ZCalendar.ZComponent comp = inv.newToVComponent(useOutlookCompatAllDayEvents, includePrivateData, includeAttaches);
/*      */           
/* 2527 */           seriesComp = comp;
/* 2528 */           comps.add(seriesComp);
/* 2529 */           seriesInv = inv;
/* 2530 */           break;
/*      */         }
/*      */       }
/* 2533 */       for (Invite inv : invites) {
/* 2534 */         if (inv != seriesInv) {
/* 2535 */           if ((inv.hasRecurId()) && (inv.isCancel()))
/*      */           {
/*      */ 
/* 2538 */             if (seriesComp != null) {
/* 2539 */               RecurId rid = inv.getRecurId();
/* 2540 */               ZCalendar.ZProperty ridProp = rid.toProperty(false);
/*      */               
/* 2542 */               ZCalendar.ZProperty exdateProp = new ZCalendar.ZProperty(ZCalendar.ICalTok.EXDATE, ridProp.getValue());
/* 2543 */               for (Iterator<ZCalendar.ZParameter> paramsIter = ridProp.parameterIterator(); paramsIter.hasNext();) {
/* 2544 */                 ZCalendar.ZParameter param = (ZCalendar.ZParameter)paramsIter.next();
/* 2545 */                 exdateProp.addParameter(param);
/*      */               }
/* 2547 */               seriesComp.addProperty(exdateProp);
/*      */             }
/*      */             else {
/* 2550 */               ZCalendar.ZComponent comp = inv.newToVComponent(useOutlookCompatAllDayEvents, includePrivateData, includeAttaches);
/*      */               
/* 2552 */               if (comp != null) {
/* 2553 */                 comps.add(comp);
/*      */               }
/*      */             }
/*      */           } else {
/* 2557 */             ZCalendar.ZComponent comp = inv.newToVComponent(useOutlookCompatAllDayEvents, includePrivateData, includeAttaches);
/*      */             
/* 2559 */             if (comp != null)
/* 2560 */               comps.add(comp);
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/* 2565 */     return (ZCalendar.ZComponent[])comps.toArray(new ZCalendar.ZComponent[0]);
/*      */   }
/*      */   
/* 2568 */   public Iterator<Alarm> alarmsIterator() { return this.mAlarms.iterator(); }
/*      */   
/* 2570 */   public void addAlarm(Alarm alarm) { this.mAlarms.add(alarm); }
/*      */   
/* 2572 */   public List<Alarm> getAlarms() { return this.mAlarms; }
/*      */   
/*      */ 
/*      */ 
/*      */   public void clearAlarms()
/*      */   {
/* 2578 */     this.mAlarms.clear();
/*      */   }
/*      */   
/* 2581 */   public Iterator<ZCalendar.ZProperty> xpropsIterator() { return this.mXProps.iterator(); }
/*      */   
/* 2583 */   public void addXProp(ZCalendar.ZProperty prop) { this.mXProps.add(prop); }
/*      */   
/*      */   public void removeXProp(String xpropName) {
/* 2586 */     for (Iterator<ZCalendar.ZProperty> iter = this.mXProps.iterator(); iter.hasNext();) {
/* 2587 */       ZCalendar.ZProperty prop = (ZCalendar.ZProperty)iter.next();
/* 2588 */       if (prop.getName().equalsIgnoreCase(xpropName))
/* 2589 */         iter.remove();
/*      */     }
/*      */   }
/*      */   
/* 2593 */   public ZCalendar.ZProperty getXProperty(String xpropName) { for (ZCalendar.ZProperty prop : this.mXProps) {
/* 2594 */       if (prop.getName().equalsIgnoreCase(xpropName))
/* 2595 */         return prop;
/*      */     }
/* 2597 */     return null;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public void validateDuration()
/*      */     throws ServiceException
/*      */   {
/* 2607 */     if (this.mStart == null)
/* 2608 */       return;
/* 2609 */     if (!isTodo()) {
/* 2610 */       ParsedDuration durMinimum = this.mStart.hasTime() ? ParsedDuration.parse(false, 0, 0, 0, 0, 1) : ParsedDuration.parse(false, 0, 1, 0, 0, 0);
/*      */       
/*      */ 
/* 2613 */       if ((this.mEnd != null) && (this.mEnd.compareTo(this.mStart) <= 0)) {
/* 2614 */         this.mEnd = this.mStart.add(durMinimum);
/* 2615 */       } else if (this.mDuration != null) {
/* 2616 */         ParsedDateTime et = this.mStart.add(this.mDuration);
/* 2617 */         long durMillis = et.getUtcTime() - this.mStart.getUtcTime();
/* 2618 */         if (durMillis <= 0L) {
/* 2619 */           this.mDuration = durMinimum;
/*      */         }
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public boolean isSameOrNewerVersion(Invite other)
/*      */   {
/* 2630 */     if (other == null) return false;
/* 2631 */     int thisSeq = getSeqNo();
/* 2632 */     int otherSeq = other.getSeqNo();
/* 2633 */     return thisSeq >= otherSeq;
/*      */   }
/*      */   
/*      */   public boolean isNewerVersion(Invite other) {
/* 2637 */     if (other == null) return false;
/* 2638 */     int thisSeq = getSeqNo();
/* 2639 */     int otherSeq = other.getSeqNo();
/* 2640 */     return thisSeq > otherSeq;
/*      */   }
/*      */   
/*      */   public Invite newCopy() {
/* 2644 */     List<ZAttendee> attendees = new ArrayList(this.mAttendees.size());
/* 2645 */     for (ZAttendee at : this.mAttendees) {
/* 2646 */       attendees.add(new ZAttendee(at));
/*      */     }
/* 2648 */     ZOrganizer org = this.mOrganizer != null ? new ZOrganizer(this.mOrganizer) : null;
/* 2649 */     Invite inv = new Invite(this.type, this.mMethod != null ? this.mMethod.toString() : null, this.mTzMap != null ? this.mTzMap.clone() : null, this.mCalItem, this.mUid, this.mStatus, this.mPriority, this.mPercentComplete, this.mCompleted, this.mFreeBusy, this.mTransparency, this.mClass, this.mStart, this.mEnd, this.mDuration, this.mRecurrence, this.mIsOrganizer, org, attendees, this.mName, this.mLocation, this.mFlags, this.mPartStat, this.mRsvp, this.mRecurrenceId, this.mDTStamp, this.mLastModified, this.mSeqNo, this.mLastFullSeqNo, 0, 0, 0, this.mSentByMe, this.mDescription, this.mDescHtml, this.mFragment, new ArrayList(this.mComments), new ArrayList(this.mCategories), new ArrayList(this.mContacts), this.mGeo != null ? new Geo(this.mGeo.getLatitude(), this.mGeo.getLongitude()) : null, this.mUrl);
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/* 2659 */     inv.setClassPropSetByMe(classPropSetByMe());
/* 2660 */     inv.setDontIndexMimeMessage(getDontIndexMimeMessage());
/* 2661 */     inv.mLocalOnly = this.mLocalOnly;
/* 2662 */     inv.mDescInMeta = this.mDescInMeta;
/*      */     
/* 2664 */     inv.clearAlarms();
/* 2665 */     for (Alarm alarm : this.mAlarms) {
/* 2666 */       inv.addAlarm(alarm.newCopy());
/*      */     }
/* 2668 */     return inv;
/*      */   }
/*      */   
/*      */   private static String limitIntegerRange(String value, int min, int max, String defaultValue) {
/* 2672 */     String retval = defaultValue;
/* 2673 */     if (value != null) {
/*      */       try {
/* 2675 */         int num = Integer.parseInt(value);
/* 2676 */         if (num < min) {
/* 2677 */           retval = Integer.toString(min);
/* 2678 */         } else if (num > max) {
/* 2679 */           retval = Integer.toString(max);
/*      */         } else
/* 2681 */           retval = value;
/*      */       } catch (NumberFormatException e) {}
/*      */     }
/* 2684 */     return retval;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static boolean isOrganizerMethod(String method)
/*      */   {
/* 2693 */     ZCalendar.ICalTok methodTok = ZCalendar.ICalTok.lookup(method);
/* 2694 */     return isOrganizerMethod(methodTok);
/*      */   }
/*      */   
/*      */   public static boolean isOrganizerMethod(ZCalendar.ICalTok method) {
/*      */     boolean isRequesting;
/* 2699 */     if (method != null) { boolean isRequesting;
/* 2700 */       switch (method) {
/*      */       case REQUEST: 
/*      */       case PUBLISH: 
/*      */       case ADD: 
/*      */       case CANCEL: 
/*      */       case DECLINECOUNTER: 
/* 2706 */         isRequesting = true;
/* 2707 */         break;
/*      */       case REPLY: case REFRESH: case COUNTER: default: 
/* 2709 */         isRequesting = false;break;
/*      */       }
/*      */     } else {
/* 2712 */       isRequesting = true;
/*      */     }
/* 2714 */     return isRequesting;
/*      */   }
/*      */   
/*      */   public void sanitize(boolean throwException) throws ServiceException {
/* 2718 */     if ((this.mUid == null) || (this.mUid.length() == 0)) {
/* 2719 */       if (throwException) {
/* 2720 */         throw ServiceException.INVALID_REQUEST("missing UID; subject=" + this.mName, null);
/*      */       }
/* 2722 */       ZimbraLog.calendar.warn("UID missing; subject=" + this.mName);
/*      */     }
/* 2724 */     this.mUid = fixupIfOutlookUid(this.mUid);
/*      */     
/*      */ 
/* 2727 */     if ((isTodo()) && (this.mStart != null) && (this.mEnd == null)) {
/* 2728 */       this.mStart = null;
/*      */     }
/*      */     
/* 2731 */     ParsedDateTime dt = this.mStart != null ? this.mStart : this.mEnd;
/* 2732 */     if (dt == null)
/*      */     {
/* 2734 */       setIsAllDayEvent(false);
/* 2735 */     } else if (!dt.hasTime())
/*      */     {
/* 2737 */       setIsAllDayEvent(true);
/* 2738 */     } else if (!dt.hasZeroTime())
/*      */     {
/* 2740 */       setIsAllDayEvent(false);
/*      */     }
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/* 2748 */     if ((isOrganizerMethod(this.mMethod)) && (hasOtherAttendees()) && (!hasOrganizer())) {
/* 2749 */       if (throwException) {
/* 2750 */         throw ServiceException.INVALID_REQUEST("ORGANIZER missing when ATTENDEEs are present; UID=" + this.mUid + ", subject=" + this.mName, null);
/*      */       }
/*      */       
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/* 2758 */       ZimbraLog.calendar.warn("ORGANIZER missing; clearing ATTENDEEs to avoid confusing clients; UID=" + this.mUid + ", subject=" + this.mName);
/*      */       
/* 2760 */       clearAttendees();
/*      */     }
/*      */     
/*      */ 
/*      */ 
/* 2765 */     if ((this.mStart != null) && (this.mEnd != null) && (this.mEnd.compareTo(this.mStart) < 0)) {
/* 2766 */       this.mEnd = ((ParsedDateTime)this.mStart.clone());
/*      */     }
/*      */     
/* 2769 */     if ((this.mRecurrence != null) && (this.mStart == null)) {
/* 2770 */       if (throwException) {
/* 2771 */         throw ServiceException.INVALID_REQUEST("recurrence used without DTSTART; UID=" + this.mUid + ", subject=" + this.mName, null);
/*      */       }
/* 2773 */       ZimbraLog.calendar.warn("recurrence used without DTSTART; removing recurrence; UID=" + this.mUid + ", subject=" + this.mName);
/* 2774 */       this.mRecurrence = null;
/*      */     }
/*      */     
/*      */ 
/*      */ 
/* 2779 */     if ((isRecurrence()) && (this.mStart != null) && (this.mEnd != null) && (!this.mStart.getTimeZone().equals(this.mEnd.getTimeZone()))) {
/* 2780 */       ZimbraLog.calendar.warn("recurrence uses different time zones in DTSTART and DTEND; forcing DTEND to DTSTART time zone; UID=" + this.mUid + ", subject=" + this.mName);
/*      */       
/*      */ 
/* 2783 */       this.mEnd.toTimeZone(this.mStart.getTimeZone());
/*      */     }
/*      */     
/* 2786 */     this.mPercentComplete = limitIntegerRange(this.mPercentComplete, 0, 100, null);
/* 2787 */     this.mPriority = limitIntegerRange(this.mPriority, 0, 9, null);
/*      */     
/*      */ 
/* 2790 */     Set<String> tzids = getReferencedTZIDs();
/* 2791 */     this.mTzMap.reduceTo(tzids);
/*      */     
/*      */ 
/* 2794 */     if (this.mLastModified == 0L) {
/* 2795 */       this.mLastModified = this.mDTStamp;
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public static void setDefaultAlarm(Invite inv, Account acct)
/*      */     throws ServiceException
/*      */   {
/* 2805 */     inv.clearAlarms();
/* 2806 */     int prefNonAllDayMinutesBefore = (int)acct.getLongAttr("zimbraPrefCalendarApptReminderWarningTime", 0L);
/*      */     
/* 2808 */     int hoursBefore = 0;
/* 2809 */     int minutesBefore = 0;
/* 2810 */     if (!inv.isAllDayEvent()) {
/* 2811 */       hoursBefore = 0;
/* 2812 */       minutesBefore = prefNonAllDayMinutesBefore;
/* 2813 */     } else if (prefNonAllDayMinutesBefore > 0)
/*      */     {
/*      */ 
/* 2816 */       hoursBefore = 18;
/* 2817 */       minutesBefore = 0;
/*      */     }
/* 2819 */     if ((minutesBefore > 0) || (hoursBefore > 0)) {
/* 2820 */       String summary = inv.getName();
/* 2821 */       Alarm newAlarm = new Alarm(Alarm.Action.DISPLAY, Alarm.TriggerType.RELATIVE, Alarm.TriggerRelated.START, ParsedDuration.parse(true, 0, 0, hoursBefore, minutesBefore, 0), null, null, 0, null, summary, null, null, null);
/*      */       
/*      */ 
/*      */ 
/* 2825 */       inv.addAlarm(newAlarm);
/*      */     }
/*      */   }
/*      */   
/*      */   public Set<String> getReferencedTZIDs() {
/* 2830 */     Set<String> tzids = new HashSet();
/*      */     
/* 2832 */     if ((this.mStart != null) && (this.mStart.hasTime())) {
/* 2833 */       ICalTimeZone tz = this.mStart.getTimeZone();
/* 2834 */       if (tz != null) {
/* 2835 */         tzids.add(tz.getID());
/*      */       }
/*      */     }
/* 2838 */     if ((this.mEnd != null) && (this.mEnd.hasTime())) {
/* 2839 */       ICalTimeZone tz = this.mEnd.getTimeZone();
/* 2840 */       if (tz != null) {
/* 2841 */         tzids.add(tz.getID());
/*      */       }
/*      */     }
/* 2844 */     if (this.mRecurrenceId != null) {
/* 2845 */       ParsedDateTime dt = this.mRecurrenceId.getDt();
/* 2846 */       if (dt.hasTime()) {
/* 2847 */         ICalTimeZone tz = dt.getTimeZone();
/* 2848 */         if (tz != null) {
/* 2849 */           tzids.add(tz.getID());
/*      */         }
/*      */       }
/*      */     }
/* 2853 */     Recurrence.IRecurrence recur = getRecurrence();
/* 2854 */     if (recur != null)
/* 2855 */       tzids.addAll(Recurrence.getReferencedTZIDs(recur));
/* 2856 */     return tzids;
/*      */   }
/*      */   
/*      */   public void clearPrivateInfo()
/*      */   {
/* 2861 */     this.mName = null;
/* 2862 */     this.mDescription = null;
/* 2863 */     this.mDescHtml = null;
/* 2864 */     this.mComments.clear();
/* 2865 */     this.mLocation = null;
/* 2866 */     this.mAttendees.clear();
/* 2867 */     this.mPriority = null;
/* 2868 */     this.mPercentComplete = null;
/* 2869 */     this.mCompleted = 0L;
/* 2870 */     this.mCategories.clear();
/* 2871 */     this.mContacts.clear();
/* 2872 */     this.mGeo = null;
/* 2873 */     this.mAlarms.clear();
/* 2874 */     this.mXProps.clear();
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public Invite makeInstanceInvite(ParsedDateTime recurIdDt)
/*      */     throws ServiceException
/*      */   {
/* 2884 */     if (!isRecurrence())
/* 2885 */       return null;
/* 2886 */     Invite instInv = newCopy();
/* 2887 */     instInv.setLocalOnly(true);
/* 2888 */     instInv.setRecurrence(null);
/* 2889 */     RecurId rid = new RecurId(recurIdDt, RecurId.RANGE_NONE);
/* 2890 */     instInv.setRecurId(rid);
/* 2891 */     ParsedDateTime dtEnd = recurIdDt.add(instInv.getEffectiveDuration());
/* 2892 */     instInv.setDtStart(recurIdDt);
/* 2893 */     instInv.setDtEnd(dtEnd);
/* 2894 */     return instInv;
/*      */   }
/*      */   
/*      */   public boolean isHighPriority()
/*      */   {
/* 2899 */     if (this.mPriority != null) {
/* 2900 */       int prio = 0;
/*      */       try {
/* 2902 */         prio = Integer.parseInt(this.mPriority);
/*      */       } catch (NumberFormatException e) {}
/* 2904 */       return (prio >= 1) && (prio <= 4);
/*      */     }
/* 2906 */     return false;
/*      */   }
/*      */   
/* 2909 */   public boolean isLowPriority() { if (this.mPriority != null) {
/* 2910 */       int prio = 0;
/*      */       try {
/* 2912 */         prio = Integer.parseInt(this.mPriority);
/*      */       } catch (NumberFormatException e) {}
/* 2914 */       return (prio >= 6) && (prio <= 9);
/*      */     }
/* 2916 */     return false;
/*      */   }
/*      */   
/*      */   private static boolean isHexDigits(String str) {
/* 2920 */     int len = str.length();
/* 2921 */     for (int i = 0; i < len; i++) {
/* 2922 */       char ch = str.charAt(i);
/* 2923 */       if (((ch < '0') || (ch > '9')) && ((ch < 'A') || (ch > 'F')) && ((ch < 'a') || (ch > 'f')))
/*      */       {
/* 2925 */         return false; }
/*      */     }
/* 2927 */     return true;
/*      */   }
/*      */   
/*      */ 
/*      */   public static boolean isOutlookUid(String uid)
/*      */   {
/* 2933 */     if (uid == null)
/* 2934 */       return false;
/* 2935 */     int len = uid.length();
/* 2936 */     if ((len >= 82) && (len % 2 == 0) && (isHexDigits(uid))) {
/* 2937 */       String upper = uid.toUpperCase();
/* 2938 */       return upper.startsWith("040000008200E00074C5B7101A82E008");
/*      */     }
/* 2940 */     return false;
/*      */   }
/*      */   
/*      */   public static String fixupIfOutlookUid(String uid)
/*      */   {
/* 2945 */     return isOutlookUid(uid) ? uid.toUpperCase() : uid;
/*      */   }
/*      */   
/*      */   public static abstract interface InviteVisitor
/*      */   {
/*      */     public abstract void visit(Invite paramInvite)
/*      */       throws ServiceException;
/*      */   }
/*      */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/mailbox/calendar/Invite.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */